原文地址
下面我将介绍一下如何为一个List<People>
这样的List里面的某个属性进行去重。顺便介绍一下两个实体之间如何用lambda进行复制
OK,我们先来写一个Person实体
package com.dzy.test.lambda;
/**
* Created by itar
*/
public class Person {
private int age;
private String name;
private String country;
private String address;
private String phone;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", country='" + country + '\'' +
", address='" + address + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
然后写一个会被复制的People实体,其实这种情况很常见,一般就是从数据库种拿到的entity然后复制到dto中
package com.dzy.test.lambda;
/**
* Created by itar
*/
public class People {
private int age;
private String name;
private String country;
private String address;
private String phone;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "People{" +
"age=" + age +
", name='" + name + '\'' +
", country='" + country + '\'' +
", address='" + address + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
主要的测试类:
package com.dzy.test.lambda;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Created by itar
*/
public class TestPeopleLambda {
private static List<Person> personList=new ArrayList<>();
static {
for (int i = 1; i <= 20; i++) {
Person person=new Person();
person.setAge(i);
person.setName("xiaoming"+i);
//待会儿筛选属性用到
if (i%10==0){person.setAddress("shanghai10村");}else{
person.setAddress("shanghai"+i+"村");
}
person.setCountry("中国"+i+"区");
personList.add(person);
}
}
@Test
public void testLambda(){
//下面我要将personList转化为peoplelist里面去,少一个或者多一个属性,看下我怎么做
List<People> peopleList = personList.stream().map(person -> {
People people = new People();
BeanUtils.copyProperties(person, people);
return people;
//下面我做个工作,将shanghai 10村的人合并到一起,也就是说最终会输出17个人people,看看
}).filter(distinctByKey(People::getAddress)).collect(Collectors.toList());
//打印出来的实体只有19个,说明我们筛选成功了,而且成功转成了people实体了
peopleList.forEach(System.out::println);
}
/**
* 定义一个过滤器进行去重
* 不涉及到共享变量,没有线程安全问题
* 为什么是这样写的,因为上面的filter是需要一个Predicate返回的参数的
* 用concurrentHashMap里面的putIfAbsent进行排重
*/
public static<T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
}
}
到这里,我们的去重工作就完成了,主要起作用的是distinctByKey 这个方法的使用和编写,本例中仅仅作用于address,还可以定制一些其他的,可以继续filter,添加第二个去重的要求。
over!
方法2
2018年添加方法2
List<Person> distinctList = personList.stream().collect(
Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName()))),
ArrayList::new));
主要是利用了collectingAndThen 这个方法,第二种方法比较简便