项目中经常会用到 list.stream() 的操作,比如说比较两个list、list分组统计、筛选、转map这些,有的时候不太熟练的就经常会忘记要怎么写,还得翻以前的代码看看是怎么写的。所以干脆把用过的都总结记录起来,以后忘了的话就不用打开这个项目那个项目翻代码了。
先创建两个list并添加好数据
@Data
public static class Entity{
private int id;
private String name;
private String attribute;
private String type;
public Entity(){}
public Entity(int id,String name,String attribute,String type){
this.id = id;
this.name = name;
this.attribute = attribute;
this.type = type;
}
}
private static List<Entity> list1 = new ArrayList<>();
private static List<Entity> list2 = new ArrayList<>();
static {
list1.add(new Entity(1,"迅羽","异能","雷伤"));
list1.add(new Entity(2,"炽翎","异能","火伤"));
list1.add(new Entity(3,"月轮","机械","雷伤"));
list1.add(new Entity(4,"白夜","生物","物伤"));
list1.add(new Entity(5,"云墨","异能","火伤"));
list1.add(new Entity(6,"识宝","生物","物伤"));
list2.add(new Entity(1,"迅羽","异能","雷伤"));
list2.add(new Entity(3,"影骑士月轮","机械","雷伤"));
list2.add(new Entity(5,"云墨丹心","异能","火伤"));
list2.add(new Entity(6,"识宝","生物","火伤"));
list2.add(new Entity(7,"理律","机械","冰伤"));
list2.add(new Entity(8,"空律","生物","物伤"));
list2.add(new Entity(9,"雷律","异能","雷伤"));
list2.add(new Entity(10,"炎律","异能","火伤"));
}
1、list转map
// 以id为key,实体对象为value
Map<Integer, Entity> map1 = list1.stream().collect(Collectors.toMap(Entity::getId, Function.identity(), (key1, key2) -> key2));
// 以某个属性或多个属性为key,某个属性值为value
Map<String, String> map2 = list1.stream().collect(Collectors.toMap(item -> fetchGroupKey(item), Entity::getAttribute));
/**
* 多个属性用 # 号分隔
*/
private String fetchGroupKey(Entity entity){
return entity.getId() +"#" +entity.getName();
}
2、获取指定属性值,并转为对应的list:获取list2中所有name,并转为list
List<String> nameList = list2.stream().map(Entity::getName).collect(Collectors.toList());
3、list根据指定属性过滤数据:只保留attribute为生物的元素
List<Entity> filterResult = list2.stream().filter(item -> "生物".equals(item.getAttribute())).collect(Collectors.toList());
4、list取交集
// 4.1 根据整个元素取交集,这里需要元素的全部属性值相同
List<Entity> intersection1 = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
// 4.2 根据某个属性或多个属性值取交集:根据id和name
List<Entity> intersection2 = list1.stream().filter(item -> list2.parallelStream().anyMatch(tm->item.getId() == tm.getId()
&& item.getName().equals(tm.getName()))).collect(Collectors.toList());
5、list取差集
// 5.1 根据整个元素取差集
List<Entity> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList());
// 5.2 根据属性取差集:根据id,在list1中过滤出list2没有的数据(可以有多个属性)
List<Entity> reduce2 = list1.stream().filter(item -> (list2.parallelStream().noneMatch(tm ->
item.getId() == tm.getId()))).collect(Collectors.toList());
6、list取并集并去重
// 必须要元素的全部相同才能去重
List<Entity> union = Stream.of(list1, list2).flatMap(Collection::stream).distinct().collect(Collectors.toList());
7、list去重
// 7.1 用distinct:必须要元素的全部相同才能去重
List<Entity> unique1 = list1.stream().distinct().collect(Collectors.toList());
// 7.2 用TreeSet:根据attribute去重
List<Entity> unique2 = list1.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(o -> o.getAttribute()))), ArrayList::new));
/**
* 7.3 用toMap:
* oldValue、newValue代表旧值、新值。
* 当stream构造Map时,会先调用Map的get方法获取该key对应的旧值,如果该值为null,则不会调用BinaryOperator函数;
* 如果不为null,则会把获取的旧值与新值作为参数传给函数执行,然后把函数的返回值作为新值put到Map中。
*/
// 这里是把oldValue作为函数返回值
List<Entity> unique3 = new ArrayList<>(list1.stream()
.collect(Collectors.toMap(Entity::getAttribute, Function.identity(), (oldValue, newValue) -> oldValue)).values());
// 这里是把newValue作为函数返回值
List<Entity> unique4 = new ArrayList<>(list1.stream()
.collect(Collectors.toMap(Entity::getAttribute, Function.identity(), (oldValue, newValue) -> newValue)).values());
8、两个list根据id,筛选出某个属性值不相同的元素
// 根据id,过滤出名字和类型不相同的元素
List<Entity> updateFilter = list1.stream().filter(item ->(list2.parallelStream().anyMatch(tm->item.getId() == tm.getId()
&& (!item.getName().equals(tm.getName()) || !item.getType().equals(tm.getType())) ))).collect(Collectors.toList());
9、根据某个属性进行分组统计
// 根据type对元素进行分组,并统计每个type的个数
Map<String, List<Entity>> groupingBy = list2.stream().collect(Collectors.groupingBy(item -> item.getType()));
for (Map.Entry<String, List<Entity>> entry : groupingBy.entrySet()) {
System.out.println(entry.getKey()+"的个数为:"+entry.getValue().size());
}
10、排序
List<Entity> descSort = descSortList(list1);
List<Entity> ascSort = ascSortList(descSort);
//根据id倒序
public List<Entity> descSortList(List<Entity> list){
Collections.sort(list, new Comparator<Entity>() {
@Override
public int compare(Entity o1, Entity o2) {
return o2.getId() - o1.getId();
}
});
return list;
}
//根据id升序
public List<Entity> ascSortList(List<Entity> list){
Collections.sort(list, new Comparator<Entity>() {
@Override
public int compare(Entity o1, Entity o2) {
return o1.getId() - o2.getId();
}
});
return list;
}
// 3.16排序补充
//list= list.stream().sorted(Comparator.comparing(Entity::getId)).collect(Collectors.toList());//根据id升序
list= list.stream().sorted(Comparator.comparing(Entity::getId).reversed()).collect(Collectors.toList());//根据id降序
---------------------------------- 3.16更新
11、分组求和:某个属性值相同的元素进行分组求和
//name是用户姓名,score是用户分数,根据用户姓名统计这个用户的总分数
//方法一
Map<String, Double> sum = all.stream().collect(Collectors.toMap(User::getName, User::getScore, Double::sum));
//方法二
Map<String, Double> sum1 = all.stream().collect(Collectors.groupingBy(User::getName, Collectors.collectingAndThen(Collectors.summarizingDouble(User::getScore), DoubleSummaryStatistics::getSum)));
//方法三
Map<String, Double> sum2 = all.stream().collect(Collectors.groupingBy(User::getName, Collectors.collectingAndThen(Collectors.mapping(User::getScore, Collectors.reducing(Double::sum)), Optional::get)));
以上,差不多就这些,如果还有其他的使用欢迎在评论区补充。