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

标签: Java, Tips

添加新评论