1. 程式人生 > >List物件去重的幾種方法

List物件去重的幾種方法

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 + "]";
	}

}