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 等