开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
上一期介绍了Stream的常用API,这一期结合实际开发中的一些例子,来进一步熟悉Stream的使用。
1.List去重
一个list去除重复的数据,在开发中再常见不过了,那么如何处理呢,下面给出几种解决方案。
1.1 利用distinct去重
利用distinct可以对类似于List的集合进行去重,比如:
List<String> strings = Arrays.asList("123", "321", "123", "234", "231");
List<String> collect = strings.stream().distinct().collect(Collectors.toList());
System.out.println(collect);
输出:
[123, 321, 234, 231]
打开调试工具,可以清晰的看到重复数据123只保留了一个。但是,我们在开发中很多时候都是需要对对象集合进行去重,或者以对象的某一个属性或多个属性进行去重,那么又怎么办呢?我们接着往下看。
1.2 List<对象>去重
public class Person {
private String name;
private int age;
private String address;
// 省略部分代码
}
List<Person> list = new ArrayList<>();
list.add(new Person("张三", 23, "成都市"));
list.add(new Person("李四", 25, "绵阳市"));
list.add(new Person("王五", 23, "成都市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("刘七", 21, "成都市"));
// 根据姓名和年龄对数据去重
List<Person> resultList = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getName() + ";" + s.getAge()))), ArrayList::new)
);
System.out.println(resultList);
这里你需要对几个属性进行去重,直接在Comparator.comparing()里面拼接上对应的属性就好了。输出:
[Person{name='刘七', age=21, address='成都市'}, Person{name='张三', age=23, address='成都市'},Person{name='李四', age=25, address='绵阳市'},Person{name='王五', age=23, address='成都市'},Person{name='赵六', age=26, address='绵阳市'}]
对于List<Map<String,String>>的去重,也可以用这种方式,看下面的例子
List<Map<String,String>> list = new ArrayList<>();
Map<String,String> mapOne = new HashMap<>();
mapOne.put("name","张三");
mapOne.put("age","12");
mapOne.put("address","成都市");
list.add(mapOne);
Map<String,String> mapTwo = new HashMap<>();
mapTwo.put("name","张三");
mapTwo.put("age","12");
mapTwo.put("address","成都市");
list.add(mapTwo);
Map<String,String> mapThree = new HashMap<>();
mapThree.put("name","李四");
mapThree.put("age","12");
mapThree.put("address","成都市");
list.add(mapThree);
System.out.println("========去重前:=========");
list.forEach(System.out::println);
// 根据姓名和年龄对数据进行去重
List<Map<String, String>> resultList = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.get("name") + ";" + s.get("age")))), ArrayList::new)
);
System.out.println("========去重后:=========");
resultList.forEach(System.out::println);
可以看出,也是在Comparator.comparing()里面对需要去重的属性值进行拼接而已。输出:
========去重前:=========
{address=成都市, name=张三, age=12}
{address=成都市, name=张三, age=12}
{address=成都市, name=李四, age=12}
========去重后:=========
{address=成都市, name=张三, age=12}
{address=成都市, name=李四, age=12}
另外,分享一个面试题,List如何快速去重?直接利用set集合的特性我们知道,list集合的数据是有序可重复的,但是set集合的数据是不可重复的,利用这一特性可以对list进行去重。将list的数据放入set中不就去重了么
2. List与Map互转
2.1 List<对象>转Map<String,String>类型
直接看例子:
List<Person> list = new ArrayList<>();
list.add(new Person("张三", 23, "成都市"));
list.add(new Person("李四", 25, "绵阳市"));
list.add(new Person("王五", 23, "成都市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("刘七", 21, "成都市"));
// 将list转为map<String,Object>结构,map的key为姓名,value为对象本身
Map<String, Person> map = list.stream().collect(Collectors.toMap(Person::getName, person -> person));
System.out.println(map);
一运行,好家伙,报错了原来是map的key重复了,不用担心,我们稍微改造下,当key值重复时,我们取第一个值
// 将list转为map<String,Object>结构,map的key为姓名,value为对象本身
Map<String, Person> map = list.stream().collect(Collectors.toMap(Person::getName, person -> person, (person1, person2) -> person1));
输出:
{刘七=Person{name='刘七', age=21, address='成都市'},
李四=Person{name='李四', age=25, address='绵阳市'},
张三=Person{name='张三', age=23, address='成都市'},
王五=Person{name='王五', age=23, address='成都市'},
赵六=Person{name='赵六', age=26, address='绵阳市'}}
完美解决了,这个在开发中需要注意这一点,要考虑map的key可能重复的情况
2.2 List<对象>转Map<String,List<对象>>类型
有时候,我们会对list的某一个属性进行分组,然后得到每组属性对应的list是什么,就可以用到。
List<Person> list = new ArrayList<>();
list.add(new Person("张三", 23, "成都市"));
list.add(new Person("李四", 25, "绵阳市"));
list.add(new Person("王五", 23, "成都市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("赵六", 26, "绵阳市"));
list.add(new Person("刘七", 21, "成都市"));
// 对年龄进行分组,获取每组的数据
Map<Integer, List<Person>> collect = list.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println(collect);
输出:
{21=[Person{name='刘七', age=21, address='成都市'}],
23=[Person{name='张三', age=23, address='成都市'}, Person{name='王五', age=23, address='成都市'}],
25=[Person{name='李四', age=25, address='绵阳市'}],
26=[Person{name='赵六', age=26, address='绵阳市'}, Person{name='赵六', age=26, address='绵阳市'}]}
2.3 Map<String,String>转List<对象>
我们直接看一个例子
Map<Integer, String> map = new HashMap<>();
map.put(1, "成都市");
map.put(2, "绵阳市");
map.put(3, "宜宾市");
// 将map的value值转化为list
List<String> collect = map.values().stream().collect(Collectors.toList());
System.out.println(collect);
输出:
[成都市, 绵阳市, 宜宾市]
快快用起来吧。