
【Guava 教學】(7)Multiset、Multimap 與 BiMap
如果有個清單,想要取得清單中不重複的元素,最快的方式就是使用 JDK 中的 List<String> words = Arrays.asList("one", "two", "three", "one", "three"); Set<String> wordSet = new HashSet<>(words); out.println(wordSet); // [two, one, three] 如果不單只是想取得清單中不重複元素,也想要知道清單中重複元素個數,那麼你也許會這麼撰寫: List<String> words = Arrays.asList("one", "two", "three", "one", "three"); Map<String, Integer> counts = new HashMap<>(); for(String word : words) { Integer count = counts.get(word); counts.put(word, count == null ? 1 : count + 1); } out.println(counts); // {two=1, one=2, three=2} 如果不單只是計數,在後續迭代時也想要取得重複元素呢?你可能會如此撰寫: List<String> words = Arrays.asList("one", "two", "three", "one", "three"); Map<String, List<String>> wordBag = new HashMap<>(); for(String word : words) { List<String> repeatedWds = wordBag.get(word); if(repeatedWds == null) { repeatedWds = new ArrayList<>(); wordBag.put(word, repeatedWds); } repeatedWds.add(word); } 透過 for(Map.Entry<String, Integer> entry : counts.entrySet()) { int count = entry.getValue(); for(int c = 0; c < count; c++) { String word = entry.getKey(); 用迭代的 word 做些事 ... } } 這些程式碼當然都可以自己撰寫,只不過 Guava 的 List<String> words = Arrays.asList("one", "two", "three", "one", "three"); Multiset<String> wordBag = HashMultiset.create(words); out.println(wordBag); // [two, one x 2, three x 2] for(String word : wordBag) { 用迭代的 word 做些事 ... } 多重集合(Multiset)是集合(Set)概念的推廣(Generalization),集合中相同元素只能出現一次,元素在集合中只是有或無兩個屬性,多重集合則允許相同元素出現多次,元素在集合中具有重複次數(Occurrence)的概念,多重集合又稱為集合包(Bag)。 Guava 的
在資料結構上, List<Letter> letters = ...; Map<Integer, List<Letter>> letterBag = new HashMap<>(); for (Letter letter : letters) { Integer zipCode = letter.getZipCode(); List<Letter> sameZipLetters = letterBag.get(zipCode); if (sameZipLetters == null) { sameZipLetters = new ArrayList<>(); letterBag.put(zipCode, sameZipLetters); } sameZipLetters.add(letter); } // {106=[Letter(106, adr1), Letter(106, adr2)], 804=[Letter(804, adr3), Letter(804, ..)]} out.println(letterBag); 對這樣的需求,單純使用 Guava 的 List<Letter> letters = ...; Multimap<Integer, Letter> letterBag = HashMultimap.create(); for(Letter letter : letters) { letterBag.put(letter.getZipCode(), letter); } // {106=[Letter(106, adr1), Letter(106, adr2)], 804=[Letter(804, adr3), Letter(804, ..)]} out.println(letterBag); JDK 的 選用 List<String> words = Arrays.asList("one", "two", "three", "one", "three"); Multimap<String, String> wordBag = ArrayListMultimap.create(); for(String word : words) { wordBag.put(word, word); } 如此重複的字串,才會被個別收集起來,如果你選用了 要注意的是, public static Integer getId(Map<Integer, String> users, String name) { for(Map.Entry<Integer, String> userEntry : users.entrySet()) { if(name.equals(userEntry.getValue())) { return userEntry.getKey(); } } return null; } 使用 public static Integer getId(Map<Integer, String> users, String name) { BiMap<Integer, String> userBiMap = HashBiMap.create(users); return userBiMap.inverse().get(name); } 為了要能夠達到從值取鍵的這個目的, |