Java Stream API
[TOC]
Java8 中 的Steam 可以定义为来自来源的元素序列,Streams支持对元素进行聚合操作,这里的元素指的是为流提供数据的集合和 数组,在聚合操作中我们可以根据我们需求来获取出符合我们要求的数据
在操作Stream 流之前我们应该知道,Streams API 都是直接针对流的操作,因此首先我们要先会创建一个 Steam。
在粒度级别,Collection 和 Stream 之间的区别与计算事物的时间有关。甲Collection是一个存储器内数据结构,其中认为所述数据结构当前具有的所有值。必须先计算集合中的每个元素,然后才能将其添加到集合中。Stream 在概念上是一个管道,其中元素是按需计算的。
这个概念带来了显着的编程优势。这个想法是,用户将仅从 Stream 中提取他们需要的值,并且这些元素仅在需要时(对用户不可见)生成。这是生产者-消费者关系的一种形式。
在 Java 中,java.util.Stream
表示可以对其执行一个或多个操作的流。流操作要么是中间的,要么是终端的。
的终端操作返回一个特定类型的结果和中间操作返回流本身,所以我们可以连锁的一排的多个方法,以在多个步骤中执行该操作。
流是在源上创建的,例如java.util.Collection
喜欢List
或Set
。在Map
不直接支持,我们可以创建映射键,值。
流操作可以顺序或并行执行。当并行执行时,它被称为并行流
1. 创建流
下面给出了一些创建流的方式
1.1 Stream.of()
public static void main(String[] args)
{
// 通过Stream.of 方法获取一个数据流
Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
stream.forEach(p -> System.out.println(p));
}
1.2 Stream.of(数组)
我们可以通过引入一个数组的方式生成一个流
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of( new Integer[]{1,2,3,4,5,6,7,8,9} );
stream.forEach(p -> System.out.println(p));
}
1.3 列表.steam( 常用)
工作中我们经常使用通过一个集合来获取一个流,流中的元素都是来自List
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
stream.forEach(p -> System.out.println(p));
}
1.4 Stream.generate() 或者 Stream.iterate()
// 下面的代码中,我们从给的元素中创建一个流,但是我们只是限制去获取 20 个,因此我们用 limit 进行限制
public static void main(String[] args)
{
Stream<Integer> randomNumbers = Stream
.generate(() -> (new Random()).nextInt(100));
randomNumbers.limit(20)
.forEach(System.out::println);
}
1.5 字符串字符流
public static void main(String[] args)
{
IntStream stream = "12345_abcdefg".chars();
stream.forEach(p -> System.out.println(p));
//OR
Stream<String> stream = Stream.of("A$B$C".split("\\$"));
stream.forEach(p -> System.out.println(p));
1.6 Stream.builder()
通过创建一个builder 方法创建一个建造器,同样生成流
Stream<Object> name = Stream.builder().add("name").build();
2. Stream Collector(流收集器)
在对流中的元素执行中间件操作后,我们可以 使用流收集器方法再次将处理过的元素收集到一个集合中
2.1 将stream中的元素收集到一个集合中
在给定的例子中,首先,我们在整数 1 到 10 上创建一个流。然后我们处理流元素以找到所有偶数.最后将所有的偶数收集到一个集合中
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
List<Integer> evenNumbersList = stream.filter(i -> i%2 == 0)
.collect(Collectors.toList());
System.out.print(evenNumbersList);
}
2.2 将stream 中元素收集到数组中
和上一个实例中的需求一样,这次我们是将偶数收集到一个数组中
List<Integer> result = new ArrayList<>();
for (Integer x : list) {
if (x % 2 == 0) {
result.add(x);
}
}
Integer[] evenNumbersArr = list.stream().filter(x -> x% 2 == 0).toArray(Integer[]::new);
3. 流操作
- 中间流操作 操作之后返回的还是一个Steam 流,
终端操作 操作之后直接对六中的数据进行处理,没有返回值
List<String> memberNames = new ArrayList<>();memberNames.add("Amitabh");memberNames.add("Shekhar");memberNames.add("Aman");memberNames.add("Rahul");memberNames.add("Shahrukh");memberNames.add("Salman");memberNames.add("Yana");memberNames.add("Lokesh");
3.1.1 Stream.filter (过滤)
过滤操作接收了一个Predicate 类型的方法, 返回一个 符合 predicate 要求的steam 流,比如从以上的集合中获取 是 A 开头的城市
memberNames.stream().filter((s) -> s.startsWith("A")) .forEach(System.out::println);
3.1.2 Stream.map (转换,映射)
map 操作 我认为是一种转换或者映射的操作,例如 我们将集合中的小写 字符都转变成大写字符
memberNames.stream().filter((s) -> s.startsWith("A")) .map(String::toUpperCase) .forEach(System.out::println);
3.1.3 Stream.sorted (排序)
排序接口可以直接对集合中的元素进行排序, 在java 8 之前我们要对list 中的元素进行排序,我们可能比较复杂,要用 sort方法,并用Compare 匿名内部类,写法比较繁琐
memberNames.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return 0; } });
但是 现在使用java 8 之后,我们可以用另一种方式,进行排序
memberNames.stream().sorted() .map(String::toUpperCase) .forEach(System.out::println);
这种方式默认的方式是正向排序,如果想反向排序,可以使用 reverse 方法进行改变顺序
3.2 终端操作
终端操作会返回终端操作的结果,
3.2.1 Stream.foreach
foreach 是一个遍历迭代的功能
memberNames.forEach(System.out::println);
3.2.2 collect 收集
collect 是一个收集的方法,从Stream 中获取符合的数据 然后储存到一个集合中
List<String> memNamesInUppercase = memberNames.stream().sorted() .map(String::toUpperCase) .collect(Collectors.toList()); System.out.print(memNamesInUppercase);
3.2.3 match 匹配
match 是 我针对match 类方法的一种统称,和 之前讲的filter 差不多,但是功能上稍微强大一些,而且方法比较多
//只要 元素中 有一个符合 是A 开始的就返回Trueboolean matchedResult = memberNames.stream() .anyMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); // 如果元素全部是用A开头的,那么返回TruematchedResult = memberNames.stream() .allMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); //如果元素没有用A 开头的,返回truematchedResult = memberNames.stream() .noneMatch((s) -> s.startsWith("A")); System.out.println(matchedResult);
4.2.4. Stream.count ()
计数的一个终端操作,返回一个long 型的 返回值
long totalMatched = memberNames.stream() .filter((s) -> s.startsWith("A")) .count(); System.out.println(totalMatched);
4.2.5. Stream.reduce ()
reduce 原意 减少,缩小 ,根据指定的计算模型将stream中的值计算到一个最终结果,
针对这个方法有一个博主文章将的特别好,在此借鉴一下 java8 reduce
总结 针对stream 常用操作方法进行了记录
中间操作
- filter
- map
- distinct
- sorted
- peek
- limit
- skip
终端操作
- foreach
- toArray
- reduce
- foreachOrdered
- min
- max
- count
- anyMatch
- collect
- findfirst 等