谓词筛选filter
谓词是一个返回boolean的函数,也就是条件,通过这个条件进行筛选。
@Test
public void testFilterMapLimit(){
List<Entity> entities = Lists.newArrayList(new Entity(100), new Entity(12), new Entity(33), new Entity(41));
List<Integer> collect = entities.stream()
.filter(entity -> entity.getId() < 100)
.map(Entity::getId)
.collect(Collectors.toList());
System.out.println(collect);
}
这里,filter的参数就是一个谓词,配合filter,可以筛选结果,只有返回值是true的item会通过。
去重复distinct
distinct()
截短流limit
limit(n)
跳过元素skip
skip(n)。 通过limit(n)形成互补关系。
映射map
map, stream的核心操作。接收一个参数,用来把一个对象转换为另一个。demo同上。下面看具体需求。
/**
* Returns a stream consisting of the results of applying the given
* function to the elements of this stream.
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* @param <R> The element type of the new stream
* @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to apply to each element
* @return the new stream
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
接收一个Function函数,然后返回Stream. 而Function在前面已经介绍过了。我们看核心的方法。
/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
Function函数的功能就是把参数转换成另一个类型的对象,返回。也就是a -> {return b;}。
瞥一眼Peek
上面map的需求特别多,但有时候我并不想返回另一个对象,我只是想要把原来的对象加工一个下,还是返回原来的对象。用map也是可以的,只要返回同一个对象就行。但IDEA会推荐用peek()。
比如,我想把list的user全部取出来,把updateDate更新为当前时间。
@Test
public void testPeek(){
final List<Integer> list = Lists.newArrayList(1,2,3,4);
System.out.println(collect);
}
源码里是这样写的
/**
* Returns a stream consisting of the elements of this stream, additionally
* performing the provided action on each element as elements are consumed
* from the resulting stream.
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* <p>For parallel stream pipelines, the action may be called at
* whatever time and in whatever thread the element is made available by the
* upstream operation. If the action modifies shared state,
* it is responsible for providing the required synchronization.
*
* @apiNote This method exists mainly to support debugging, where you want
* to see the elements as they flow past a certain point in a pipeline:
* <pre>{@code
* Stream.of("one", "two", "three", "four")
* .filter(e -> e.length() > 3)
* .peek(e -> System.out.println("Filtered value: " + e))
* .map(String::toUpperCase)
* .peek(e -> System.out.println("Mapped value: " + e))
* .collect(Collectors.toList());
* }</pre>
*
* @param action a <a href="package-summary.html#NonInterference">
* non-interfering</a> action to perform on the elements as
* they are consumed from the stream
* @return the new stream
*/
Stream<T> peek(Consumer<? super T> action);
而Consumer同样也在之前出现过
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
也就是说,peek()的本意是将对象取出来,消一遍,并不是像我的说的那样返回原对象,因为参数并不是Function, 而是Consumer。我之所以这么说是因为Function也可以做到这个功能,只要将返回值变为当前对象即可。而peek里,我们可以修改当前对象的属性,也是会生效的。
流的扁平化faltMap
我们前面讲的函数都是处理一个序列,一个list,一个Stream里的数据。如果一个Stream的元素也是另一个stream呢?我还想把这个Stream的元素的stream打散,最终输出一个stream。比如下面这个例子。统计单词列表中出现的字母。
final List<String> words = Lists.newArrayList( "Hello", "worlds");