Stream操作list

傻男人 1年前 ⋅ 617 阅读

java8 Stream操作list

Stream是什么

Stream又称为流,可以将集合转换为一种流,对集合中的每个元素进行一系列的流式操作。

数据源 ------转换为-->流---->进行中间操作---->终止操作

多个中间操作可以连接起来形成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何处理,在终止操作时一次性全部处理

转化为流

使用stream()或者parallelStream()方法将集合转为流

  • stream()单线程(确切的说是PC中默认的最大线程数,单核/多核)
  • parallelStream()并行的

中间操作

filter 筛选

过滤操作,只返回为true的数据

/**
* filter  接收lambda,从流中排除某些元素
*/
public static void testFilter(){
  // 中间操作
  // 使用的Predicate   boolean test(T t);
  Stream<String> stream = list.stream().filter(e ->{
                                                System.out.println("filter中间操作");
                                                 return e.equals("张三");
                                               }
                                              );
  // 这时中间操作还没有执行执行
  System.out.println("----中间操作结束----");
  //终止操作:一次执行全部操作
  stream.forEach(
    System.out::println
  );
}

distinct 去重

/**
* distinct 筛选,通过流所生成元素的hashCode()和equals()方法去重
*/
public static void testDistinct(){
  list.stream().distinct().forEach(System.out::println);
}

limit 切片

返回前n个元素

/**
* limit 截断流,使其元素不超过给定数量
*/
public static void testLimit(){
  list.stream().limit(2).forEach(System.out::println);
}

skip 去除(跳过)前n个元素

/**
* skip 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回空流
*/
public static void testSkip(){
  list.stream().skip(2).forEach(System.out::println);
}
public static void testLimitAndSkip(){
  System.out.println("--------先limit再skip---------");
  list.stream().limit(2).skip(1).forEach(System.out::println);
  System.out.println("--------先skip再limit---------");
  list.stream().skip(1).limit(2).forEach(System.out::println);
}

注意:在limit和skip搭配使用的时候,两个的顺序不同会导致结果不同

  • 先进行limit,再进行skip时,会选择前两个数据,然后在跳过第一个数据,只会筛选出一条数据
  • 先进行skip,再进行limit时,会先跳过一条数据,在选择剩下数据的前两条,最终会筛选出两条数据

sorted 排序

排序可以有两种排序方式,第一种是进行排序的类要实现Comparable接口,第二种是在自己实现一个Comparator接口

/**
 * sorted()自然排序  Comparable 所要排序的类必须实现Comparable接口
 */
public static void test(){
    list.stream().map(User::getAge).sorted().forEach(System.out::println);
}

/**
* sorted(Comparator com) 定制排序(Comparator)
*/
public static void test1(){
  list.stream().sorted(
    (o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return -1;
      }
      return 0;
    }
  ).forEach(System.out::println);
}

map 映射

/**
* map 接收lambda,将元素转换为其他形式或提取信息。接收一个函数作为函数,
* 该函数会被应用到每个元素上,并将其映射成一个新的元素
*
* 如果函数返回的是一个流的话,使用map会使得流里存储着多个流
*/
public static void testMap(){
  // 使用Function  R apply(T t);
  list.stream().map(User::getAge).forEach(System.out::println);
}

flatmap

/**
* flatMap  接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*
* 如果函数返回的是一个流,使用flatMap会使得函数返回的流中的元素放到一个流中
*/
public static void testFlatMap(){
  // 要求Function  R apply(T t);中返回值是一个Stream流
  List<String> add = new ArrayList<>();
  add.add("添加元素");
  List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
  strings.stream().flatMap(
    TestStreamApi1::joinStream
  ).forEach(System.out::println);
}

终止操作

allMatch

流中所有元素都要匹配给定的条件为true,否则为false 相当于且

boolean isSex = list.stream().allMatch(l -> l.getSex() == 0);
System.out.println(isSex);

anyMatch

流中有任意一条数据匹配给定的条件为true,否则为false 相当于并

boolean isSex = list.stream().anyMatch(l -> l.getSex() == 0);
System.out.println(isSex);

noneMatch

流中所有的数据都不匹配给定条件时为true,否则为false 相当于非

boolean isSex = list.stream().noneMatch(l -> l.getSex() == 0;
System.out.println(isSex);

findFirst

找到第一个元素

User user = list.stream().sorted(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return -1;
      } else if(o1.getAge() < o2.getAge()){
        return 1;
      }
      return 0;
    })
  ).findFirst().get();
  System.out.println(user);

findAny

找到其中任意一个元素

User user = list.stream().filter(l -> l.getSex() == ).findAny().get();
System.out.println(user);

count

返回流中元素的数量

long count = list.stream().count();
System.out.println(count);

max

返回流中根据比较之后的最大值元素

User user = list.stream().max(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return 1;
      } else if(o1.getAge() < o2.getAge()){
        return -1;
      }
      return 0;
    })
  ).get();
System.out.println(user);

min

返回流中根据比较之后的最小值元素

User user = list.stream().min(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return 1;
      } else if(o1.getAge() < o2.getAge()){
        return -1;
      }
      return 0;
    })
  ).get();
  System.out.println(user);

归约和收集

归约reduce

使用reduce来进行运算

/**
* 归约  将流中元素反复结合起来,得到一个值
* reduce(T identity, BinaryOperator<T> accumulator) /BinaryOperator<T> accumulator/U identity,
*                  BiFunction<U, ? super T, U> accumulator,
*                  BinaryOperator<U> combiner
*/
public static void testReduce(){
  List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
  // BinaryOperator  二元运算   R apply(T t, U u);
  int sum = list.stream().reduce((x, y) -> x+y).get();
  System.out.println(sum);
}

收集collect

根据不同的收集器collect(Collectors.toList())、collect(Collectors.toSet())来返回不同的集合

//收集 collect -- 将流转换为其他形式 接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
// Collector是一个接口  有一个Collectors提供了各种转换方式
  List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
  System.out.println(strings);

常用的一些操作

user实体类

@Data
public class User implements Serializable {

    private Long id;

    private String name;

    private int age;
}

数据准备

List<User> list = ListUtils.asList(
          new User(1L,"张三",20),
          new User(2L,"李四",25),
          new User(3L,"王五",30),
          new User(4L,"赵六",40),
          new User(5L,"张三",50),
          new User(6L,"李四",60),
          new User(7L,"王五",70),
          new User(8L,"赵六",80),
          new User(9L,"王麻子",90),
          new User(9L,"王麻子",90)
        );
按照名字相同的分组,返回Map<String,List>
Map<String,List<User>> map = list.stream().collect(Collectors.groupingBy(User::getName));
返回大于50岁以上的用户
List<User> collect = list.stream().filter(item -> item.getAge() > 50).collect(Collectors.toList());
返回user的所有id
List<Long> collect = list.stream().map(User::getId).collect(Collectors.toList());
去除重复的user
List<User> collect = list.stream().distinct().collect(Collectors.toList());
转化为map结构
Map<String,User> map = list.stream().collect(Collectors.toMap(User::getId,e->e));
排序
 List<User> collect = list.stream().sorted((o1,o2) -> (o1.getId() < o2.getId() ? 1 : -1 ) ).collect(Collectors.toList());
最大值与最小值
User user = list.stream().min((o1, o2) -> o1.getId() > o2.getId() ? 1 : -1).get();
User user1 = list.stream().max((o1, o2) -> o1.getId() > o2.getId() ? 1 : -1).get();

Optional<User> userMax = list.stream().collect(Collectors.maxBy(Comparator.comparing(user::getAge)));
Optional<User> userMinAge = list.stream().collect(Collectors.minBy(Comparator.comparing(user::getAge)));
用户年龄的总和与平均值
//对应的还有summingLong、summingDouble。
int totalAge4 = list.stream().collect(Collectors.summingInt(User::getAge));
//对应的还有averagingLong、averagingDouble。
double avgAge = list.stream().collect(Collectors.averagingDouble(User::getAge));
一次性得到元素个数、总和、均值、最大值、最小值
//对应的还有summarizingLong、summarizingDouble。
IntSummaryStatistics statistics = list.stream().collect(Collectors.summarizingInt(User::getAge));
获取名字为张三用户
List<User> collect = list.stream()
          .filter(item -> "zhangsan".equals(student.getName()))
            .collect(Collectors.toList());
获取id>4并且只获取前面两条的数据
List<User> list1 = list.stream()
                .filter(item -> item.getId()>4)
                .limit(2)
                .collect(Collectors.toList());
获取id>4并且不要前面2天的数据
 List<User> list1 = list.stream()
                .filter(item -> item.getId()>4)
                .skip(2)
                .collect(Collectors.toList());
先按照名字分组后面按照年龄分组
Map<String, Map<Integer, List<User>>> groups2 = list.stream().collect(
                Collectors.groupingBy(User::getName,  // 一级分组,名字
                Collectors.groupingBy(User::getAge)));  // 二级分组,按年龄
获取user的名字除去相同的名字并用逗号分隔
String collect1 = list.stream().map(User::getName).distinct().collect(Collectors.joining(","));

全部评论: 0

    我有话说: