List根据对象属性去重 && List根据数量分组
List根据对象属性去重 && List根据数量分组
List根据对象属性去重
现有一个Student类,类中有一个name属性,需要根据name属性对一个装有Student的list进行去重:Student
public class Student {
private String name;
public Student() { }
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
现在有一个装有Student的list:
List<Student> list = new ArrayList<>();
Collections.addAll(list,
new Student("张三"),
new Student("李四"),
new Student("王五"),
new Student("张三"),
new Student("李四"),
new Student("赵六"));
System.out.println("去重之前: ");
System.out.println("list = " + list);
/* 输出:
去重之前:
list = [张三, 李四, 王五, 张三, 李四, 赵六]
*/
第一种方式:
ArrayList<Student> afterList = list.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getName())))
, ArrayList::new));
System.out.println("第一种去重之后: ");
System.out.println("afterList = " + afterList);
/* 输出:
第一种去重之后:
afterList = [张三, 李四, 王五, 赵六]
*/
第一眼看到这段代码愣是没看懂这是在去重,写成下面这种方式比较好理解:
第二种方式:
Set<Student> set = new TreeSet<>(Comparator.comparing(Student::getName));
set.addAll(list);
List<Student> afterList2 = new ArrayList<>(set);
System.out.println("第二种去重之后: ");
System.out.println("afterList2 = " + afterList2);
/* 输出:
第二种去重之后:
afterList2 = [张三, 李四, 王五, 赵六]
*/
其原理都是利用TreeSet的构造方法:public TreeSet(Comparator<? super E> comparator)
(JDK 1.8)来进行去重处理,并且可以根据多个属性来去重。
这里我特意看了一下HashSet,发现HashSet并没有类似构造方法,也就是说根据属性去重必须使用TreeSet
List根据数量分组
有时候需要把一个list拆分成多个list分批处理,这时候可以使用这种方式:
List<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5", "6", "7", "8");
List<List<String>> resultList = new ArrayList<>();
//多少个一组
int groupNum = 3;
//当前游标
int current = 0;
while (current < list.size()) {
resultList.add(new ArrayList<>(list.subList(current, Math.min((current + groupNum), list.size()))));
current += groupNum;
}
System.out.println("resultList = " + resultList);
/* 输出:
resultList = [[1, 2, 3], [4, 5, 6], [7, 8]]
*/
这里使用了list.subList(fromIndex, toIndex)
这个方法(范围包头不包尾,因此toIndex
可以直接使用list.size()
),需要注意的是,subList()
方法返回的是源list的视图,而非一个新的ArrayList,对subList进行添加删除操作会影响到源list,因此subList需要作为new ArrayList<>(subList)
的参数来添加到resultList里面。
类似的坑还有一个Arrays.asList()
方法,使用Arrays.asList()
获得的List对象不能添加删除元素,因此一般也是作为new ArrayList<>(Arrays.asList(array))
的参数来使用,这也是常用的数组转List。