java 根据对象某个属性进行去重
在开发中可能会遇到很多需要去重的情况,比如Person对象有name跟age两个属性,需要根据age进行去重
方式一
1.1 根据name去重
public class test {
public static void main(String[] args) {
List<Person> ps=new ArrayList<>();
ps.add(new Person(11,"tom"));
ps.add(new Person(11,"张三"));
ps.add(new Person(12,"tom"));
ps.add(new Person(11,"tom"));
//根据name进行去重
List<Person> list = ps.stream().collect(
Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(p -> p.getName()))), ArrayList::new)
);
list.forEach(System.out::println);
System.out.println("-----------");
//根据name与age进行去重
List<Person> list1 = ps.stream().collect(
Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(p -> p.getName()+";"+p.getAge()))), ArrayList::new)
);
list1.forEach(System.out::println);
}
}
@Data
class Person{
String name;
int age;
Person(int age,String name){
this.name=name;
this.age=age;
}
}
执行结果
Person(name=tom, age=11)
Person(name=张三, age=11)
-----------
Person(name=tom, age=11)
Person(name=tom, age=12)
Person(name=张三, age=11)
1.2 获取list中所有的name并去重
//获取list中所有的name
List<String> list=ps.stream().map(Person::getName).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
list.forEach(System.out::println);
执行结果
tom
张三
1.3 过滤list中年龄大于11的人
List<Person> list=ps.stream().filter(p -> p.getAge()>11).collect(Collectors.toList());
list.forEach(System.out::println);
执行结果
Person(name=tom, age=12)
1.4 根据年龄进行分组
Map<Integer,List<Person>> map=ps.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println(map.get(11));
执行结果:
[Person(name=tom, age=11), Person(name=张三, age=11), Person(name=tom, age=11)]
1.5 list转map(key不能重复,否则会报错)
List<Person> ps=new ArrayList<>();
ps.add(new Person(11,"tom"));
ps.add(new Person(11,"张三"));
// 将list转换为 map,注意name作为 key 不能重复,应先做去重处理,否则会报错
Map<String, Integer> map = ps.stream().collect(Collectors.toMap(Person::getName, Person::getAge));
map.forEach((s, i) -> System.out.println(s+"|"+i));
// 用 name 做 key 将 List 转成 Map
Map<String, Person> map1 = ps.stream().collect(Collectors.toMap(Person::getName, item -> item));
//将list转成Map, 若key重复,则使用旧的,解决key重复报错的问题
Map<String, Person> map2 = ps.stream().collect(Collectors.toMap(Person::getName, Function.identity(), (oldValue, newValue) -> oldValue));
//根据name进行去重,转换为Map,然后再转换为list
ps.stream().collect(Collectors.toMap(Person::getName, Function.identity(), (oldValue, newValue) -> oldValue))
.values()
.stream();
for (Person p : ps) {
System.out.println(p);
}
执行结果
张三|11
tom|11
1.6:排序
public class test {
public static void main(String[] args) {
List<Person> ps=new ArrayList<>();
ps.add(new Person(11,"tom"));
ps.add(new Person(11,"张三"));
ps.add(new Person(12,"tom"));
ps.add(new Person(11,"tom"));
// 按照年龄从高到低排序
// 方式一
ps.sort((o1, o2)
-> o1.getAge() == null ? 1 : (o2.getAge() == null ? -1 : o2.getAge().compareTo(o1.getAge())));
System.out.println(ps);
// 方式二
ps.sort(Comparator.comparing(Person::getAge, (o1, o2)
-> o1 == null ? 1 : (o2 == null ? -1 : o2.compareTo(o1))));
System.out.println(ps);
// 方式三 (age 字段不能为 null, null 会导致排序失败)
ps.sort(Comparator.comparing(Person::getAge).reversed());
System.out.println(ps);
// 先按照年龄排序,再按照姓名从高到低排序
ps.sort(Comparator.comparing(Person::getAge, (o1, o2)
-> o1 == null ? 1 : (o2 == null ? -1 : o1.compareTo(o2))).thenComparing((o1, o2)
-> o1.getName() == null ? 1 : (o2.getName() == null ? -1 : o2.getName().compareTo(o1.getName()))));
System.out.println(ps);
}
}
@Data
class Person{
String name;
Integer age;
Person(Integer age,String name){
this.name=name;
this.age=age;
}
}
执行结果
[Person(name=tom, age=12), Person(name=tom, age=11), Person(name=张三, age=11), Person(name=tom, age=11)]
[Person(name=tom, age=12), Person(name=tom, age=11), Person(name=张三, age=11), Person(name=tom, age=11)]
[Person(name=tom, age=12), Person(name=tom, age=11), Person(name=张三, age=11), Person(name=tom, age=11)]
[Person(name=张三, age=11), Person(name=tom, age=11), Person(name=tom, age=11), Person(name=tom, age=12)]
方式二
2.1 根据age去重
List<Person> ps=new ArrayList<>();
ps.add(new Person(11,"tom"));
ps.add(new Person(11,"张三"));
ps.add(new Person(12,"tom"));
ps.add(new Person(11,"tom"));
ps.stream()
//或者这样写 Collectors.toMap(m -> m.getUserId(),
.collect(Collectors.toMap(Person::getAge,
Function.identity(), (oldValue, newValue) -> oldValue))
.values()
.stream()
.forEach(System.out::println); //打印
执行结果:
Person(name=tom, age=11)
Person(name=tom, age=12)
代码讲解
ps.stream()
.collect(Collectors.toMap(Person::getAge,
Function.identity(), (oldValue, newValue) -> oldValue))
如上代码返回的是Map<Integer,Person>集合,所以list可以与map进行转换,若key重复,则使用旧的值。
方式三
3.1 利用Collectors.toCollection去重
List<Person> ps=new ArrayList<>();
ps.add(new Person(11,"tom"));
ps.add(new Person(11,"张三"));
ps.add(new Person(12,"tom"));
ps.add(new Person(11,"tom"));
ps.stream()
.collect(Collectors.toCollection(() ->
new TreeSet<>(Comparator.comparing(Person::getName))))
.stream()
.forEach(System.out::println); //打印
利用TreeSet原理去重,TreeSet内部使用的是TreeMap,使用指定Comparator比较元素,如果元素相同,则新元素代替旧元素,如果不想要返回TreeSet类型,那也可以使用Collectors.collectingAndThen转换成ArrayList,也可以用new ArrayList(set),原理一样,如下:
List<Person> list = ps.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
-> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new));
** 如果想根据多个去重,可以将上述方法中的Comparator.comparing(Person::getName))修改为Comparator.comparing(p -> p.getName() +";" + p.getAge() )) 这样就是根据两个字段去重,中间的 ; 作用就是为了增加辨识度,也可以不加这个 ; ,无论多少个字段去重只用在这里用+连接就可以了