1. List中簡單元素去重(String等)
public List<String> removeStringListDupli(List<String> stringList) {
Set<String> set = new LinkedHashSet<>();
set.addAll(stringList);
stringList.clear();
stringList.addAll(set);
return stringList;
}
或使用Java8的寫法:
List<String> unique = list.stream().distinct().collect(Collectors.toList());
1
2. List中對象去重
比如現在有一個 Person類:
public class Person {
private Long id;
private String name;
public Person(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
重寫Person對象的equals()方法和hashCode()方法:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (!id.equals(person.id)) return false;
return name.equals(person.name);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + name.hashCode();
return result;
}
下面對象去重的代碼:
public static void main(String[] args) {
Person p1 = new Person(1l, "jack");
Person p2 = new Person(3l, "jack chou");
Person p3 = new Person(2l, "tom");
Person p4 = new Person(4l, "hanson");
Person p5 = new Person(5l, "膠布蟲");
List<Person> persons = Arrays.asList(p1, p2, p3, p4, p5, p5, p1, p2, p2);
List<Person> personList = new ArrayList<>();
// 去重
persons.stream().forEach(p -> {
if (!personList.contains(p)) {
personList.add(p);
}
});
System.out.println(personList);
}
List 的contains()方法底層實現使用對象的equals方法去比較的,其實重寫equals()就好,但重寫了equals最好將hashCode也重寫了。
3. 根據對象的屬性去重
下面要根據Person對象的id去重,那該怎么做呢?
寫一個方法吧:
public static List<Person> removeDupliById(List<Person> persons) {
Set<Person> personSet = new TreeSet<>((o1, o2) -> o1.getId().compareTo(o2.getId()));
personSet.addAll(persons);
return new ArrayList<>(personSet);
}
通過Comparator比較器,比較對象屬性,相同就返回0,達到過濾的目的。
再來看比較炫酷的Java8寫法:
public static void main(String[] args) {
// 根據id去重
List<Person> unique = persons.stream().collect(collectingAndThen(
toCollection(() -> new TreeSet<>(comparingLong(Person::getId))), ArrayList::new)
);
}
public static void main(String[] args) {
// 根據name去重
List<Person> unique = persons.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new));
unique.forEach(p -> System.out.println(p));
}
persons這個list的streamAPI的聚合操作collect可以讓我們只關注結果,而collect方法里的collectingAndThen又是屬 於 java.util.stream.Collector,collectingAndThen操作的解釋是:先執行前面的操作,然后執行第二部操作后輸出結果。
第一步操作就是Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName)));
第二步就是將他輸出為一個新的ArrayList;
第一步操作里又是用到Collectors接口,這次用的是toCollection方法,就是將方法里的函數或者參數轉化為一個collection集合,這里,我們是將Comparator.comparing(Person::getName)轉化為一個collection,這個collection是一個TreeSet。也就是有序的。因為我們需要去掉重復的值,這個set可以做到,而我們又要保持轉化出來的collection依舊有序,所以使用的是一個TreeSet。
Comparator.comparing(Person::getName)這里呢,又用到了java.util.Comparator接口,這個接口倒是挺常用的。使用的是他的comparing方法,也就是比較參數的值是否相同,里面用到的是java8的新特性lambda表達式, :: 其實和.沒太大區別,舉個例子,最常用的System.out.println() 可以表達為System.out::println,可以達到一樣的效果。