JavaStream

Java8引入Stream,主要用来处理集合,可以执行查找,过滤,映射等操作
特点:

  1. 不是数据结构,不会保存数据
  2. 不会修改原来的值
  3. 流在中间过程中只是对操作记录,并不会立即执行(惰性求值)

Stream操作

1. 创建流

//Collection
List<String> list = new ArrayList<>();
Stream<String> OrderStream = list.stream(); //顺序流
Stream<String> parallelStream = list.parallelStream(); //并行流
//Arrays
Integer[] nums = new Integer[10];
Stream<Integer> stream = Arrays.stream(nums);
//Stream
Stream<Integer> stream1 = Stream.of(1,2,3,4,5,6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 1).limit(1);//0,1,2,3,4
Stream<Double> stream3 = Stream.generate(Math::random).limit(2);//随机生成两个double
stream3.forEach(System.out::println);//stream流的输出
//BufferedReader.lines()
BufferedReader reader = new BufferedReader(new FileReader("a.txt"));
Stream<String> stream = reader.lines();
//Pattern.splitAsStream(),分割字符串为流
Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");

2. 流操作

2.1 中间操作
  1. filter() 过滤元素
  2. limit(n) 获取n个元素
  3. skip(x) 跳过x个元素
  4. distinct() 配合hashCode(),equals()去重
  5. map() 接收一个函数(有返回值),被应用在每个元素上,并映射为一个新的元素
  6. flatMap() 接收一个函数,将每个值都换成另一个流,然后将所有流链接成一个流
  7. sorted() 自然排序,流中的元素要实现Comparable接口
  8. sorted(Comparator com) 自定义排序,自定义排序接口
  9. peek() 接受一个Consumer表达式(无返回值),可以得到流中的每个元素
2.2 终止操作
  1. allMatch() 接收一个Predicate函数,当流中元素都符合该断言返回TRUE,否则返回FALSE

  2. noneMatch() 接收一个Predicate函数,当流中每个元素都不符合该断言则返回TRUE,否则返回FALSE

  3. anyMatch() 接收一个Predicate函数,当流中有一个元素符合该断言则返回TRUE,否则返回FALSE

  4. findFirst() 返回流中的第一个元素

  5. findAny() 返回流中的任意元素

  6. count() 返回流中元素的个数

  7. max()/min() 返回流中元素的最大值,最小值

2.3 规约操作
  1. Optional<T> reduce(BinaryOperator<T> accumulator)
    第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素;第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推
  2. T reduce(T identity, BinaryOperator<T> accumulator)
    流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。
  3. <U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)
    在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。
2.4 收集操作
  1. collect() 接收一个Collector实例,将流中的元素收集为另一种数据结构

    Collector工具包

    1. Collectors.toList() 转为list
    2. Collectors.toSet() 转为set
    3. Collectors.toMap() 转为map
    4. Collectors.joining() 字符串分割连接
    5. Collectors.count() 聚合操作 求数量
    6. Collectors.maxBy(Integer:compare) 聚合操作,求最大值/最小值
    7. Collectors.summingInt() 聚合操作,求和
    8. Collectors.average() 聚合操作,求平均值
    9. Collectors.groupingBy() 分组操作
    10. Collectors.partitioningBy() 分区操作,根据条件分为两部分
    11. Collectors.reduce() 规约

实践

将List元素存储到数组

List<Integer> list=new ArrayList<>(Arrays.asList(1,2,3,4,5));
int[] arr=list.stream().mapToInt(Integer::intValue).toArray();

将数组元素存储到List

List<Integer> list2=Arrays.stream(arr).boxed().collect(Collectors.toList());

统计元素个数

Map<Integer, Long> map = Stream.of(arr)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (m1, m2) -> m2, 
                    LinkedHashMap::new));
Map<Integer, Integer> map2=Stream.of(arr).collect(Collectors.toMap(k->k, k->1,Integer::sum));
//统计并输出
Stream.of(arr).collect(Collectors.toMap(k->k, k->1,Integer::sum)).forEach((k,v)-> System.out.println(k+" : "+v));

自定义排序

int[] arr={1,5,9,7,2,3,7,-1,0,3};
arr= IntStream.of(arr).boxed().sorted(Comparator.reverseOrder()).mapToInt(Integer::intValue).toArray();

统计前k个高频元素

int[] arr={4,3,2,3,4,1,2,3,1,2,1};
int k=3;
int[] res=IntStream.of(arr)
            .boxed()
            .collect(Collectors.toMap(x->x,x->1,Integer::sum))
            .entrySet()
            .stream()
            .sorted((e1,e2)-> e2.getValue()-e1.getValue()).limit(k)
            .mapToInt(Map.Entry::getKey)
            .toArray();
posted @ 2022-05-19 09:47  流光之中  阅读(195)  评论(0编辑  收藏  举报