共计 4623 个字符,预计需要花费 12 分钟才能阅读完成。
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);
当然流收集器不仅仅能够收集到 List 中, 还有 Set,Map 等方面, 都能够通过 Collectors 进行调用实现
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 等