下面我將介紹一下如何爲一個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 這個方法,第二種方法比較簡便