List物件去重的幾種方法
阿新 • • 發佈:2019-01-30
package com.cbzk.Stream; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import org.junit.Test; /** * 如何根據物件的單個欄位去重的三種方式 * 2018年2月28日 */ public class 去重操作 { @Test public void testName() throws Exception { List<String> list = Arrays.asList("a", "b", "c", "a", new String("c")); list.stream().distinct().forEach(System.out::println); } Dog dog = new Dog("二哈", "哈哈", 3); List<Dog> dlist = Arrays.asList( new Dog("秋田犬", "產地1", 5), new Dog("西施犬", "產地2", 5), new Dog("柴犬", "產地3", 5), new Dog("秋田犬", "產地1", 5), new Dog("阿拉斯加雪橇犬", "產地5", 5), new Dog("阿拉斯加雪橇犬", "產地6", 6), new Dog("阿拉斯加雪橇犬", "產地7", 7), dog, dog); // 物件去重 ,需要實現 hashcode equals @Test public void testName2() throws Exception { List<Dog> list =new ArrayList<>(dlist); list.stream() .distinct() .forEach(System.out::println); } // 如何根據物件的單個欄位去重,java沒有直接的方法支援 // 方式1:修改hashCode和equals,最快,但是隻支援一種篩選方式 // 方式2:自定義distinctByKey方法,支援自定義條件 @Test public void testName3() throws Exception { dlist.stream() .filter(distinctByKey(p->p.getDname())) .forEach(System.out::println); } //ConcurrentHashMap支援高併發、高吞吐量的執行緒安全的HashMap,底層採用了分段鎖,Hashtable以及Collections.synchronizedMap()用的全域性鎖 public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) { Map<Object, Boolean> map = new ConcurrentHashMap<>(); return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } //方式3:使用TreeSet比較器的排序 來去重 @Test public void testName4() throws Exception { List<Dog> list =new ArrayList<>(dlist); //這裡新增一個比較器,根據getDname排序 TreeSet<Dog> tree=new TreeSet<>( Comparator.comparing(Dog::getDname) ); tree.addAll(list); // tree.forEach(System.out::println); //可能你會想,我要List 方式1:使用addall list.clear(); list.addAll(tree); list.forEach(System.out::println); //方式2:使用收集器,收集器的使用參考另外一篇文章 ... } // 如果map中有對應K對映的V且不為null則直接返回V;否則執行put @Test public void initPut() { Map<Integer,String> map=new HashMap<Integer, String>(); // putIfAbsent為Map介面中新增的一個預設方法 /** * <code> default V putIfAbsent(K key, V value) { V v = get(key); if (v == null) { v = put(key, value); } return v; } </code> */ // 如果map中有對應K對映的V且不為null則直接返回;否則執行put for (int i = 0; i < 10; i++) { map.putIfAbsent(i, "value" + i); } System.out.println(map.putIfAbsent(9, null));; System.out.println(map.putIfAbsent(10, null));; // 替換null map.putIfAbsent(10, "value10"); System.out.println(map); } } class Dog { private String dname; private String dloc; private Integer dage; public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getDloc() { return dloc; } public void setDloc(String dloc) { this.dloc = dloc; } public Integer getDage() { return dage; } public void setDage(Integer dage) { this.dage = dage; } public Dog(String dname, String dloc, Integer dage) { super(); this.dname = dname; this.dloc = dloc; this.dage = dage; } @Override public int hashCode() { final int prime = 31; int result = 1; // result = prime * result + ((dage == null) ? 0 : dage.hashCode()); // result = prime * result + ((dloc == null) ? 0 : dloc.hashCode()); result = prime * result + ((dname == null) ? 0 : dname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Dog other = (Dog) obj; // if (dage == null) { // if (other.dage != null) // return false; // } else if (!dage.equals(other.dage)) // return false; // if (dloc == null) { // if (other.dloc != null) // return false; // } else if (!dloc.equals(other.dloc)) // return false; if (dname == null) { if (other.dname != null) return false; } else if (!dname.equals(other.dname)) return false; return true; } public Dog() { super(); } @Override public String toString() { return "Dog [dname=" + dname + ", dloc=" + dloc + ", dage=" + dage + "]"; } }