List转Map

  • 1、利用Collectors.toMap方法进行转换

public Map<Long, String> getIdNameMap(List<Account> accounts) {
    return accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsername));
}
  • 2、收集对象实体本身

在开发过程中我们也需要有时候对自己的list中的实体按照其中的一个字段进行分组(比如 id ->List),这时候要设置map的value值是实体本身。

public Map<Long, Account> getIdAccountMap(List<Account> accounts) {
    return accounts.stream().collect(Collectors.toMap(Account::getId, account -> account));
}
​
public Map<Long, Account> getIdAccountMap(List<Account> accounts) {
    return accounts.stream().collect(Collectors.toMap(Account::getId, Function.identity()));
}
  • 3、重复key的情况

在list转为map时,作为key的值有可能重复,这时候流的处理会抛出个异常:Java.lang.IllegalStateException:Duplicate key。这时候就要在toMap方法中指定当key冲突时key的选择。(这里是选择第二个key覆盖第一个key)

public Map<String, Account> getNameAccountMap(List<Account> accounts) {
    return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2));
}
  • 4、用groupingBy进行分组

根据一个字段或者属性分组也可以直接用groupingBy方法,很方便。

//分组
Map<Integer, List<User>> personGroups =
userList.stream().collect(Collectors.groupingBy(User::getAge));
​
//分组,某字段之和
Map<Integer, List<User>> personGroups = 
userLIst.stream().mapToInt(User::getAge).sum();
  • 5、用partitioningBy进行分块

分块根据判断条件,分为判断结果为true和判断条件为false的两块集合

Map<Boolean, List<User>> children =
userList.stream().collect(Collectors.partitioningBy(p -> p.getAge() < 18));
//"年龄小于18:" + children.get(Boolean.TRUE);
//"年龄大于18:" + children.get(Boolean.FALSE);

List检查是否存在元素,anyMatch()、allMatch()、noneMatch()

List<Integer> list = Arrays.asList(1, 2, 3);
// anyMatch,判断条件里,任意一个元素满足,返回true
boolean flag = List.stream().anyMatch(i -> i > 1); // true
// allMatch,判断条件里,所有元素都满足,才返回true
boolean flag = list.stream().allMatch(i -> i > 1); //false
// noneMatch,判断条件里,所有元素都不满足,才返回true
boolean flag = list.stream().noneMatch(i -> i > 1); //false

List去重

//list去重
List<Integer> list = Arrays.asList(1, 1, 2, 3, 3);
List<Integer> distinctList = list.stream().distinct().collect(Collectors.toList());
//list对象,单字段去重
List<User> userList =
userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User :: getUserid))), ArrayList::new));
//list对象,多字段组合去重
List<User> userList = 
userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> {
    return o.getUserId()+","+o.getAge();
}))),ArrayList::new));
//filter去重
List<Student> studentList = studentList.stream().filter(distinctByKey(Student::getName)).collect(Collectors.toList());
​
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
}

提取List集合的一列

List<String> userNameList =
userList.stream().map(User::getUserName).collect(Collectors.toList());
​
List<String> userNameList = userList.stream().map(user->{
    return user.getRealName()
};

过滤出List中符合条件的元素

List<User> userList = userList.steam().filter(user -> a.getAge > 18 ).collect(Collectors.toList());

求List中某个元素之和

BigDecimal totalAge =
userList.stream().map(User::getAge).reduce(BigDecimal.ZERO, BigDecimal::add);

Integer int = userList.stream().collect(Collectors.summingInt(User::getAge));

Integer int = userLIst.stream().mapToInt(User::getAge).sum();

#备注:集合中累加得字段不允许为NULL

List对象过滤掉符合List属性元素

List<Integer> list = Arrays.asList(18,19,20);
List<User> filterList = userList.stream().filter(i ->!list.contains(i.getAge())).collect(Collectors.toList());

map() 转换

List<Integer> list = Arrays.asList(1, 2, 3);
List<String> newList = list.stream().map(i -> i * i).map(String::valueOf).collect(Collectors.toList());
// ["1", "4", "9"]

List排序

List<类> list; 代表某集合
 
//返回 对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(类::属性一));
 
//返回 对象集合以类属性一降序排序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,结果进行属性一降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序
 
//返回 对象集合以类属性一升序 属性二升序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
 
//返回 对象集合以类属性一降序 属性二升序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序
 
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
 
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序

//空/Null数据排序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(item -> item.属性二, Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());

//空/Null数据分组
Map<String, List<类>> map = list.stream().collect(Collectors.groupingBy(item -> {
  if (item.属性一 == null || item.属性一.equals("")) {
    return "";
  }
  return DateFormat.getDateInstance().format(item.属性一);
}))

flatMap() 展开子集合

// 假设现在有一组用户列表,每个用户有多个爱好
User user1 = new User().setId(1).setName("张三").setHobbies(Arrays.asList("看书", "听音乐"));
User user2 = new User().setId(2).setName("李四").setHobbies(Arrays.asList("看电影", "乒乓球"));
User user3 = new User().setId(3).setName("王五").setHobbies(Arrays.asList("爬山", "履行"));
List<User> users = Arrays.asList(user1, user2, user3);
// 要获取所有用户的所有的爱好,只需要这样
List<String> hobbies = users.stream().flatMap(user -> user.getHobbies().stream()).collect(Collectors.toList());
// [看书, 听音乐, 看电影, 乒乓球, 爬山, 履行]

count()计数

List<Integer> list = Arrays.asList(1, 2, 3);
long count = list.stream().filter(i -> i > 2).count();

skip()、limit() 分页

Stream.iterate(1, prev -> prev + 1)  //1开始,自增1的无限序列
    .skip(6) //  跳过前6个
    .limit(3) // 取3个元素
    .forEach(System.out::print);

reduce() 聚合

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 初始值为0,累加所有元素
Integer sum1 = list.stream().reduce(0, (x, y) -> x + y);

// 无初始值,计算结果为Optional,需要处理为空的情况后才能使用,因为结果stream中可能没有元素
Integer sum2 = list.stream().reduce(Integer::sum).orElse(0);

// 聚合时目标类型和Stream中元素类型不同时,使用此重载方法
BigDecimal sum3 = list.stream()
    .reduce(
        BigDecimal.ZERO, //初始值
        (prev, i) -> prev.add(BigDecimal.valueOf(i)), // 转换成目标类型后累加
        BigDecimal::add // 多线程的parallelStream中,对每个线程的累加结果进行汇总的方法
    );

peek() 预览

String result = Stream.of(1, 2, 3, 4)
    .map(i -> i * i)
    // 在流处理过程中提前窥视一下当前数据的样子
    // 这里会分别打印出 1, 4, 9, 16
    .peek(System.out::println)
    .map(i -> i * 2)
    .map(String::valueOf)
    .collect(Collectors.joining(","));

Stream的收集器

// 收集到ArrayList中
List<Integer> list = Stream.of(1, 2, 3).collect(Collectors.toList());
​
// 收集到HashSet中
Set<Integer> set = Stream.of(1, 2, 3).collect(Collectors.toSet());
​
// 收集到HashMap中
Map<Integer, User> map = Stream.of(
    new User().setId(1).setName("Tom"),
    new User().setId(2).setName("Jeff"),
    new User().setId(3).setName("Jack")
).collect(Collectors.toMap(
        User::getId, // 获取key的Function
        Function.identity()// 获取value的Function
    )
);
​
// 自定义收集器
// 第一种方式,用于Collection接口的子类,可以定义具体的实现类
LinkedList<Integer> linkedList = Stream.of(1, 2, 3)
    .collect(Collectors.toCollection(LinkedList::new));
​
// 第二种方式,用于任何集合,是最灵活的方式
HashSet<Integer> set = Stream.of(1, 2, 3)
    .collect(
        HashSet::new, // 定义一个用来收集结果的容器
        HashSet::add, // 定义每个元素通过什么方法收集到容器中
        HashSet::addAll // 定义并发情况下如何合并多个容器的结果
    );

聚合收集器

jdk内置了很多聚合收集器,其中reducing最为灵活,可以实现其他聚合收集器的功能。 包括:

  • Collectors.summingInt() 求和

  • Collectors.averagingInt() 求平均值

  • Collectors.maxBy() 求最大值

  • Collectors.minBy() 求最小值

  • Collectors.counting() 计数

  • Collectors.joining() 字符串连接

  • Collectors.reducing() 自定义聚合

// summing 求和
Integer sumResult = Stream.of(1, 2, 3, 4).collect(Collectors.summingInt(Integer::valueOf));
​
// averaging 求平均值
Double avgResult = Stream.of(1, 2, 3, 4).collect(Collectors.averagingInt(Integer::valueOf);
​
// maxBy,minBy 求最大最小值
Optional<Integer> maxResult = Stream.of(1, 2, 3, 4).collect(Collectors.maxBy(Comparator.comparingInt(Integer::valueOf)));
​
// counting 计数
Long countResult = Stream.of(4, 3, 2, 1).collect(Collectors.counting());
​
// joining 字符串连接
String joinResult = Stream.of("a", "b", "c", "d").collect(Collectors.joining("|"));
​
// reduce 自定义方式求和
Integer reduceResult = Stream.of(1, 2, 3, 4)
    // 两个参数分别为初始结果值和累加函数
    // 初始结果0, 每次遍历时当前元素和结果如何进行性累加
    .collect(Collectors.reducing(0, Integer::sum));
//求最大最小某字段,返回实体
User maxAgeUser = users.stream().max(Comparator.comparing(User::getAge)).get();
//求最大/最小值
int maxAge01 = users.stream().max(Comparator.comparing(User::getAge)).get().getAge();
​
double maxAge02 = users.stream().mapToDouble(User::getAge).max().getAsDouble();
​
//平均值
double avgAge01 = users.stream().mapToInt(User -> User.getAge()).average().getAsDouble();
​