JDK1.8对集合List的去重,排序,过滤,分组,统计各种处理实例详解

JDK1.8对集合List的去重,排序,过滤,分组,统计等操作,其实用到的是JDK1.8新特性stream,

首先对stream的操作可以分为两类,中间操作(intermediate operations)和结束操作(terminal operations):

中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新stream。
结束操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。
虽然大部分情况下stream是容器调用Collection.stream()方法得到的,但stream和collections有以下不同:

无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
具体流式思想概述详见:https://blog.csdn.net/zhangjun62/article/details/91874325

具体操作代码实例如下:

package com.zl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.alibaba.fastjson.JSON;


public class Test1 {

	public static void main(String[] args) {
		List<Student> resList1=new ArrayList<Student>();
		Student s1=new Student();
		s1.setName("张三");
		s1.setAge(1);
		s1.setScore(95d);
		resList1.add(s1);
		
		Student s2=new Student();
		s2.setName("李四1");
		s2.setAge(12);
		s2.setScore(90d);
		resList1.add(s2);
		
		Student s3=new Student();
		s3.setName("张三");
		s3.setAge(1);
		s3.setScore(88d);
		resList1.add(s3);
		
		Student s4=new Student();
		s4.setName("王二");
		s4.setAge(4);
		s4.setScore(87d);
		resList1.add(s4);
		
		Student s5=new Student();
		s5.setName("李四");
		s5.setAge(5);
		s5.setScore(60d);
		resList1.add(s5);
		
		
		List<Student> resList2=new ArrayList<Student>();
		Student s11=new Student();
		s11.setName("张三");
		s11.setAge(11);
		s11.setScore(69d);
		resList2.add(s11);
		
		Student s22=new Student();
		s22.setName("李四2");
		s22.setAge(12);
		s22.setScore(75d);
		resList2.add(s22);
		
		Student s33=new Student();
		s33.setName("张三2");
		s33.setAge(33);
		s33.setScore(78d);
		resList2.add(s33);
		
		Student s44=new Student();
		s44.setName("王二2");
		s44.setAge(4);
		s44.setScore(89d);
		resList2.add(s44);
		
		Student s55=new Student();
		s55.setName("李四2");
		s55.setAge(5);
		s55.setScore(82d);
		resList2.add(s55);
		
		 /*排序,按age升续排列,如果要降续则改成:(a, b) -> b.getAge() - a.getAge(); a和b都是变量名(可以按自己意愿取名字),都是list中的对象的实例*/
        List<Student> sortList = resList1.stream().sorted((a, b) -> a.getAge() - b.getAge()).collect(Collectors.toList());
        System.out.println("排序后"+JSON.toJSONString(sortList));
        //排序后[{"age":1,"name":"张三"},{"age":1,"name":"张三"},{"age":4,"name":"王二"},{"age":5,"name":"李四"},{"age":12,"name":"李四1"}]
        
        /*过滤,按照自己的需求来筛选list中的数据,比如我筛选出姓名是-张三的人,t为实例*/
        List<Student> filterList = resList1.stream().filter(t -> t.getName().equals("张三")).collect(Collectors.toList());
        System.out.println("过滤后"+JSON.toJSONString(filterList));
        //过滤后[{"age":1,"name":"张三"},{"age":1,"name":"张三"}]

        /*map, 提取对象中的某一元素,例子中我取的是每个人的name,注意list中类型对应,如果取的是age,就应该是integer类型*/
        List<String> mapList = resList1.stream().map(t -> t.getName()).collect(Collectors.toList());
        System.out.println("提取后:"+mapList);
        //提取后:[张三, 李四1, 张三, 王二, 李四]
        
        /*统计,统计所有人年龄的和,所以用mapToInt,如果是Double类型的,则需要用mapToDouble*/
        int sum = resList1.stream().mapToInt(t -> t.getAge()).sum();
        System.out.println(sum);//23
        
        /*分组, 按照字段中某个属性将list分组*/
        Map<String, List<Student>> map = resList1.stream().collect(Collectors.groupingBy(t -> t.getName()));
        System.out.println("按姓名分组"+JSON.toJSONString(map));
        //按姓名分组{"李四":[{"age":5,"name":"李四"}],"张三":[{"age":1,"name":"张三"},{"age":1,"name":"张三"}],"李四1":[{"age":12,"name":"李四1"}],"王二":[{"age":4,"name":"王二"}]}

        /*多重分组,先按名称分组,再按年龄分组*/
        Map<Object, Map<Object, List<Student>>> groupMap = resList1.stream().collect(Collectors.groupingBy(t -> t.getName(), Collectors.groupingBy(t -> ((Student) t).getAge())));
        System.out.println("按照姓名再按年龄分组:"+JSON.toJSONString(groupMap));
        

        /*多重分组,一般多重分组后都是为了统计,比如说统计每个姓名,每个年龄的总分数*/
        Map<Object, Map<Object, Double>> sumMap = resList1.stream().collect(Collectors.groupingBy(t -> t.getName(), Collectors.groupingBy(t -> t.getAge(), Collectors.summingDouble(t -> t.getScore()))));
        System.out.println(sumMap);
        
        /*stream是链式的,这些功能是可以一起使用的,例如:计算每个姓名每个年龄的及格人数*/
        Map<Object, Map<Object, Long>> integerMap = resList1.stream().filter(t -> t.getScore() >= 60).collect(Collectors.groupingBy(t -> t.getName(), Collectors.groupingBy(t -> t.getAge(), Collectors.counting())));
        System.out.println("取出及格人数:"+integerMap.get("李四").get(5));
        //["张三","李四1","王二","李四"]
        
		//2.提取出list对象中的一个属性并去重
		List<String> stIdList2=resList1.stream().map(Student::getName).distinct().collect(Collectors.toList());
		System.out.println(JSON.toJSON(stIdList2));
		
		//两个集合合并-交集(注:resList1和resList2在前或后顺序不一样,结果也不一样)
		List<Student> list = resList1.stream()
                 .filter(t->resList2.stream()
                 .anyMatch(t2->t2.getName().equals(t.getName())))
                 .collect(Collectors.toList());
		System.out.println(JSON.toJSON(list));
		//[{"score":95.0,"name":"张三","age":1},{"score":88.0,"name":"张三","age":1}]
		
		//集合中某个属性 重复值
		List<String> commonList=  list.stream().map(Student::getName).collect(Collectors.toList());
		System.out.println(JSON.toJSON(commonList));
		//["张三","张三"]
		List<String> rList=  resList1.stream().map(Student::getName).collect(Collectors.toList());
		System.out.println(JSON.toJSON(rList));
		//["张三","李四1","张三","王二","李四"]
		//求差集
		List<String> reduce1 = rList.stream().filter(item -> !commonList.contains(item)).collect(Collectors.toList());
		System.out.println(JSON.toJSON(reduce1));//["李四1","王二","李四"]
		
		//按姓名统计个数
		Map<String, Long> collect = resList1.stream().collect(Collectors.groupingBy(Student::getName,Collectors.counting()));
		System.out.println(collect);
		//{李四=1, 张三=2, 李四1=1, 王二=1}
		
		//在集合中找出姓名为”张三“的对象
		Student student = resList1.stream().filter(o -> "张三".equals(o.getName())).findAny().orElse(null);
		System.out.println(JSON.toJSON(student));
		//{"score":95.0,"name":"张三","age":1}
	}

}
public class Student {
	
	private String name ;
	private Integer age;
	private Double score;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Double getScore() {
		return score;
	}
	public void setScore(Double score) {
		this.score = score;
	}
	
}

 

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值