1. 程式人生 > >使用Maps與Sets處理集合的交差運算

使用Maps與Sets處理集合的交差運算

pri pla clas hit hid int color urn sin

技術分享
 1 import com.google.common.collect.MapDifference;
 2 import com.google.common.collect.Maps;
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 public class differenceMap {
 6     public static void main(String[] args) {
 7         Map<String, String> map = new HashMap<>();
 8         map.put("a1", "aaa");
9 map.put("a2", "bbb"); 10 map.put("a3", "ccc"); 11 Map<String, String> map1 = new HashMap<>(); 12 map1.put("z1", "zzz"); 13 map1.put("a1", "aaa"); 14 map1.put("a2", "dra"); 15 MapDifference differenceMap = Maps.difference(map, map1);
16 differenceMap.areEqual(); 17 Map<String, MapDifference.ValueDifference<String>> entriesDiffering = differenceMap.entriesDiffering(); 18 Map<String,String> entriesOnlyOnLeft = differenceMap.entriesOnlyOnLeft(); 19 Map<String,String> entriesOnlyOnRight = differenceMap.entriesOnlyOnRight();
20 Map<String,String> entriesInCommon = differenceMap.entriesInCommon(); 21 System.out.println("健在兩集合存在,但值不同的"); 22 for (Map.Entry<String, MapDifference.ValueDifference<String>> s : entriesDiffering.entrySet()) { 23 System.out.println(s.getKey()+"="+s.getValue().leftValue()); 24 System.out.println(s.getKey()+"="+s.getValue().rightValue()); 25 } 26 System.out.println("只在左邊出現的"); 27 for (Map.Entry<String,String> s :entriesOnlyOnLeft.entrySet()) { 28 System.out.println(s.getKey()+"="+s.getValue()); 29 } 30 System.out.println("只在右邊出現的"); 31 for (Map.Entry<String,String> s :entriesOnlyOnRight.entrySet()) { 32 System.out.println(s.getKey()+"="+s.getValue()); 33 } 34 System.out.println("兩者共存的"); 35 for (Map.Entry<String,String> s :entriesInCommon.entrySet()) { 36 System.out.println(s.getKey()+"="+s.getValue()); 37 } 38 39 } 40 }
Java Code

Guava Maps的提供了非常強大的處理Map運算的方法,上面是他的一個簡單的使用用例,下面我們來看下它的源碼:

一 從構造函數看起:

public static <K, V> MapDifference<K, V> difference(

Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {

  if (left instanceof SortedMap) {               首先判斷左邊集合是不是排序集合,我們先來看不是排序集合的情況,
SortedMap<K, ? extends V> sortedLeft = (SortedMap<K, ? extends V>) left;
SortedMapDifference<K, V> result = difference(sortedLeft, right);
return result;
}
return difference(left, right, Equivalence.equals()); Equivalence.equals作為判斷兩個元素是否相等的標準,詳情參加另一篇博客Base包Equivalence
}
public static <K, V> MapDifference<K, V> difference(   我們其實可以使用這個函數傳入我們想要的Equivalence
Map<? extends K, ? extends V> left,
Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence) {
Preconditions.checkNotNull(valueEquivalence); 由於外界可以直接調用,判斷參數,編寫程序中,我們要知道那些函數可以被外界調用(進行參數檢查),只是內部調用
Map<K, V> onlyOnLeft = newLinkedHashMap(); 內部調用的函數只需要在入口處進行參數判別。
Map<K, V> onlyOnRight = new LinkedHashMap<K, V>(right); // will whittle it down
Map<K, V> onBoth = newLinkedHashMap();
Map<K, MapDifference.ValueDifference<V>> differences = newLinkedHashMap(); 為什麽要用LinkedHashMap呢?
解釋一下,HashMap是不能保證插入的元素順序的,LinkedHashMap可以,這樣我們遍歷結果時,會得到和原始Map形同的鍵順序!!更符合人們的閱讀習慣!漂亮的代碼!
doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences); 這個函數是計算函數
return new MapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences); 這僅僅是個保存信息用的,沒什麽,感興趣的自己看
}

private static <K, V> void doDifference(
    Map<? extends K, ? extends V> left,
Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence,
Map<K, V> onlyOnLeft,
Map<K, V> onlyOnRight,
Map<K, V> onBoth,
Map<K, MapDifference.ValueDifference<V>> differences) {
for (Entry<? extends K, ? extends V> entry : left.entrySet()) { 也就是個遍歷。
K leftKey = entry.getKey();
V leftValue = entry.getValue();
if (right.containsKey(leftKey)) {
V rightValue = onlyOnRight.remove(leftKey);
if (valueEquivalence.equivalent(leftValue, rightValue)) {
onBoth.put(leftKey, leftValue);
} else {
differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
}
} else {
onlyOnLeft.put(leftKey, leftValue);
}
}
}
public static <K, V> SortedMapDifference<K, V> difference(  這個就是排序了的Map最後掉用的函數,區別就是使用了TreeMap。自動保持順序。
SortedMap<K, ? extends V> left, Map<? extends K, ? extends V> right) {
checkNotNull(left);
checkNotNull(right);
Comparator<? super K> comparator = orNaturalOrder(left.comparator());
SortedMap<K, V> onlyOnLeft = Maps.newTreeMap(comparator);
SortedMap<K, V> onlyOnRight = Maps.newTreeMap(comparator);
onlyOnRight.putAll(right); // will whittle it down
SortedMap<K, V> onBoth = Maps.newTreeMap(comparator);
SortedMap<K, MapDifference.ValueDifference<V>> differences = Maps.newTreeMap(comparator);
doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
return new SortedMapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
}
 


使用Maps與Sets處理集合的交差運算