趁热记录下,给未来的自己
1. 前言
在工作中,相信很多开发同学会遇到一个需求:对一个队列进行去重操作。平时注重积累,有沉淀的同学,可能就会很熟练的使用stream().distinct()等等方法; 而其他同学(包括我),此时往往需要面向谷歌编程,施展 ctrl+c & ctrl+v 大法,这次解决了,下次依旧如此,周而复始,生生不息,子子孙孙无穷尽也。。。
额。。。扯远了。言归正传,前面说到对队列去重,可以使用stream().dinstinct()。但是,当想根据队列中对象的某一个属性来进行去重的话,stream().distinct()的局限性就体现出来了。
因此,我封装了一个方法,实现对队列中的对象整体或者对象中的某一个属性值进行去重,并做了一定的单元测试。
方法说明:
-
List<T> toDistinctList:传入需要去重的队列,可以是ArrayList,LinkedList,Vector,如果传入的队列类型非以上三种,则默认返回ArrayList; -
Function<? super T, ?> objectProperty: 接收一个对象,返回一个对象,比如传入:student -> student.getName()或者用 lambda 表达式Student::getName。当为空时,则表示根据整个对象进行去重;不为空时,则表示根据对象中某一个传入的属性进行去重
2. 上代码
2.1 方法代码:
/**
* @MethodName: distinct
* @Description: 队列去重,支持对对象整体去重(此时 objectProperty 为空),也支持对对象内部某个属性去重;
* 支持对 ArrayList,LinkedList 以及 Vector 队列进行去重操作,默认返回 ArrayList
* @Param: toDistinctList 待去重队列
* @Param: objectProperty 队列中对象的属性
* @Return: java.util.List<T>
* @Exception:
* @author: arkMon
* @date: 2021/2/6 11:31
*/
public static <T> List<T> distinct(List<T> toDistinctList, Function<? super T, ?> objectProperty) {
if (CollectionUtils.isEmpty(toDistinctList)) {
if (toDistinctList instanceof ArrayList) {
return new ArrayList<>();
}
if (toDistinctList instanceof LinkedList) {
return new LinkedList<>();
}
if (toDistinctList instanceof Vector) {
return new Vector<>();
}
}
if (toDistinctList instanceof LinkedList) {
if (objectProperty == null) {
return toDistinctList.stream().distinct().collect(Collectors.toCollection(LinkedList::new));
}
return toDistinctList.stream().filter(distinctByKey(objectProperty)).collect(Collectors.toCollection(LinkedList::new));
}
if (toDistinctList instanceof Vector) {
if (objectProperty == null) {
return toDistinctList.stream().distinct().collect(Collectors.toCollection(Vector::new));
}
return toDistinctList.stream().filter(distinctByKey(objectProperty)).collect(Collectors.toCollection(Vector::new));
}
if (objectProperty == null) {
return toDistinctList.stream().distinct().collect(Collectors.toList());
}
return toDistinctList.stream().filter(distinctByKey(objectProperty)).collect(Collectors.toList());
}
public static <T> List<T> distinct(List<T> toDistinctList) {
return distinct(toDistinctList, null);
}
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> objectProperty) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(objectProperty.apply(t));
}
2.2 单元测试:
public class ListUtilTest {
List<Student> students = new ArrayList<>();
List<Student> studentsDistinct = new ArrayList<>();
List<Student> studentsDistinctByName = new ArrayList<>();
List<String> former = new ArrayList<>();
List<String> formerOnly = new ArrayList<>();
List<String> latter = new ArrayList<>();
List<String> latterOnly = new ArrayList<>();
List<String> common = new ArrayList<>();
List<String> sampleinkedList = new LinkedList<>();
List<String> expectLinkedList = new LinkedList<>();
List<String> sampleVector = new Vector<>();
List<String> expectVector = new Vector<>();
@Before
public void before() {
Student student0 = Student.builder().age(10).clazz(4).name("tom").build();
Student student1 = Student.builder().age(10).clazz(4).name("tom").build();
Student student2 = Student.builder().age(11).clazz(5).name("tom").build();
Student student3 = Student.builder().age(11).clazz(6).name("jerry").build();
students.add(student0);
students.add(student1);
students.add(student2);
students.add(student3);
studentsDistinct.add(student0);
studentsDistinct.add(student2);
studentsDistinct.add(student3);
studentsDistinctByName.add(student0);
studentsDistinctByName.add(student3);
former = Arrays.asList("a","b","c");
formerOnly = Arrays.asList("a", "b");
latter = Arrays.asList("c","d","e");
latterOnly = Arrays.asList("d", "e");
common = Arrays.asList("c");
sampleinkedList.add("a");
sampleinkedList.add("b");
sampleinkedList.add("c");
sampleinkedList.add("c");
sampleinkedList.add("d");
sampleinkedList.add("e");
sampleinkedList.add("c");
expectLinkedList.add("a");
expectLinkedList.add("b");
expectLinkedList.add("c");
expectLinkedList.add("d");
expectLinkedList.add("e");
sampleVector.add("a");
sampleVector.add("b");
sampleVector.add("c");
sampleVector.add("c");
sampleVector.add("d");
sampleVector.add("e");
sampleVector.add("c");
expectVector.add("a");
expectVector.add("b");
expectVector.add("c");
expectVector.add("d");
expectVector.add("e");
}
@Test
public void distinct() {
List<String> list0 = Arrays.asList("a", "b", "c", "c", "b", "a");
List<String> actual0 = ListUtil.distinct(list0);
List<String> expect0 = Arrays.asList("a", "b", "c");
assertEquals(expect0, actual0);
List<Integer> list1 = Arrays.asList(1, 2, 3, 3, 2, 1);
List<Integer> actual1 = ListUtil.distinct(list1);
List<Integer> expect1 = Arrays.asList(1, 2, 3);
assertEquals(expect1, actual1);
List<Double> list2 = Arrays.asList(1.0d, 2.0d, 3.0d, 3.0d, 2.0d, 1.0d);
List<Double> actual2 = ListUtil.distinct(list2);
List<Double> expect2 = Arrays.asList(1.0d, 2.0d, 3.0d);
assertEquals(expect2, actual2);
List<Float> list3 = Arrays.asList(1.0f, 2.0f, 3.0f, 3.0f, 2.0f, 1.0f);
List<Float> actual3 = ListUtil.distinct(list3);
List<Float> expect3 = Arrays.asList(1.0f, 2.0f, 3.0f);
assertEquals(expect3, actual3);
ArrayList<Object> list4 = new ArrayList<>();
List<Object> actual4 = ListUtil.distinct(list4);
List<Object> expect4 = new ArrayList<>();
assertEquals(expect4.getClass(), actual4.getClass());
LinkedList<Object> list5 = new LinkedList<>();
List<Object> actual5 = ListUtil.distinct(list5);
List<Object> expect5 = new LinkedList<>();
assertEquals(expect5.getClass(), actual5.getClass());
Vector<Object> list6 = new Vector<>();
List<Object> actual6 = ListUtil.distinct(list6);
List<Object> expect6 = new Vector<>();
assertEquals(expect6.getClass(), actual6.getClass());
List<Student> actual7 = ListUtil.distinct(students);
assertEquals(studentsDistinct, actual7);
List<Student> actual8 = ListUtil.distinct(students, Student::getName);
assertEquals(studentsDistinctByName, actual8);
List<String> actual9 = ListUtil.distinct(sampleinkedList);
assertEquals(expectLinkedList, actual9);
assertEquals(expectLinkedList.getClass(), actual9.getClass());
List<String> actual10 = ListUtil.distinct(sampleVector);
assertEquals(expectVector, actual10);
assertEquals(expectVector.getClass(), actual10.getClass());
}
}
3. TODO项
- 根据对象的任意个属性值进行去重处理