Java - Implement collection intersection

最近在處理的資料需要面對intersection的部分,在這邊要探討的是程式上的處理,主要有在

下土法煉鋼的第一版本及collection Set內使用retainAll的版本!

假設我們有八筆資料如下:

'C0014852', 'C0266015', 'ABC'
'C0014852', 'C0021070', 'ABC'
'C0014852', 'C0024299', 'ABC'
'C0014852', 'C0024211', 'ABC'
'C0014852', 'C0266015', 'DEF'
'C0014852', 'C0021070', 'DEF'
'C0014852', 'C0024299', 'DEF'
'C0014852', 'C0033122', 'DEF'

首先我們兩種型態下的各四筆資料,以type前的兩個ID算一個pair,若八筆資料中有不同型態

的兩個pair是一樣的,就算是有交集的情況!如:

'C0014852', 'C0266015', 'ABC'
'C0014852', 'C0266015', 'DEF'

作法一:

宣告一個變數:

Map<String, Integer> pair2num = new HashMap<String, Integer>();

利用此Map的key當pair,value的部分計算此pair出現幾次,計數的判斷如下:
...
if(!pair2num.containsKey(pairs)){
   pairsnum = 1;
}else{
   pairsnum = pair2num.get(pairs)+1;
}
pair2num.put(pairs, pairsnum);
...
for(Integer d : pair2num.values()){
   if(d == moreType){
      intersect_num++;
   }
}

最後針對pair2num的value做判斷,假設我今天要做兩個type的交集,那麼moreType即等於2,

在這邊要注意的是這些例子是以ID1, ID2, Type為唯一的,因此'C0014852', 'C0266015', 'ABC'

不會出現相同的兩次為條件。在上面的intersect_num就可以計算有幾組交集的組數!

作法二:

一樣針對上面的資料,宣告一變數如下:
Map<String, Set<String>> type2pair = new HashMap<String, Set<String>>();
這個變數要儲存的是,key為type (如:ABC or DEF),value為pair。
Set<String> pairs = null;
if(!type2pair.containsKey(type)){
   pairs = new HashSet<String>();
}else{
   pairs = type2pair.get(type);
}
pairs.add(pair);
type2pair.put(type, pairs);

....

for(Set<String> setElement : type2pairs.values()){
   if(tempSet == null){
      tempSet = setElement;
   }else{
      tempSet.retainAll(setElement);
   }
}
首先檢查type2pair的key是否存在,在建立此value的Set,建立完畢後。再透過迴圈,將第一

個Set儲存至tempSet內,第二個Set與第一個Set,使用retainAll method,即可以針對第一個

Set內與第二個Set相同的資料保留,不一樣的資料即會被remove,因此tempSet.size()即等於

交集的個數。切記,如果使用retainAll被排除的資料會remove,這也表示type2pairs的第一個

Set也會受影響,因為按照語法tempSet = setElement;(assign reference),type2pairs如果還要

再利用就要特別注意!

一開始是先利用作法一,後來想說看看retainAll是做啥的,結果取代後整個就比較單純!

留言