2017-07-04 45 views
2

我有一個對象流,根據它們的id定義equals和hashcode。所以我知道使用stream.distinct()我會得到一個沒有任何重複的流,但它會保持第一個外觀,而不是最後一個。如何在搜索重複項時刪除流中的第一個外觀?

這在docs明確規定:

對於有序流,不同元件的選擇是穩定 *(對於重複元件,在碰到第一齣現的元件 *順序被保留。)

那麼我怎麼能有一個沒有重複的流,但保持最後的外觀呢?

例如,如果我有這個項目列表1,2,3,1,4,5

如果我申請distinct()我會得到1,2,3,4,5,我期待:2,3,1,4,5。我怎樣才能做到這一點?

+3

您是否嘗試顛倒訂單,刪除重複,然後再次顛倒訂單? –

+0

反向流。採取獨特的。相反的結果。 – talex

+2

我嚴重懷疑你可以使用流來實現這一點。這需要流功能「向前看」,以查看流中稍後是否出現副本,或者返回並追溯刪除已通過輸出的項目。這些都不是真正屬於溪流'性格'的一部分。 – ajb

回答

8

定製的toMap集電極與存取順序LinkedHashMap是一個好的開始,例如:

Stream.of(1, 2, 3, 1, 4, 5) 
     .collect(Collectors.toMap(
       key -> key, 
       value -> value, 
       (oldValue, newValue) -> newValue, 
       () -> new LinkedHashMap<>(16, 0.75f, true) 
     )) 
     .values() 
     .stream() 
     .forEach(System.out::println); 

維護項目的最後一個出場的任務意味着,你將不得不完全消耗原始流反正在生成新流的第一個元素之前,收集並創建一個新流並不是那麼糟糕。正如評論中所建議的那樣,反轉,應用截然不同和再次反轉,將完全消耗原始和「獨特」流,因此使用專用收集器應該更好。

3

Oleg's answer是絕對正確的,我在這裏張貼做同樣的事情的其他方式的基礎上,他使用訪問順序LinkedHashMap的想法。

沒有流:

Map<Integer, Integer> map = new LinkedHashMap<>(16, 0.75f, true); // access order 
Arrays.asList(1, 2, 3, 1, 4, 5) 
    .forEach(e -> map.put(e, e)); // just put 
List<Integer> list1 = new ArrayList<>(map.values()); // discard the map 

System.out.println(list1); // [2, 3, 1, 4, 5] 

有了流,使用自定義收集:

List<Integer> list2 = Stream.of(1, 2, 3, 1, 4, 5) 
    .collect(Collector.of(
     () -> new LinkedHashMap<Integer, Integer>(16, 0.75f, true), 
     (m, e) -> m.put(e, e), 
     (m1, m2) -> { m1.putAll(m2); return m1; }, 
     m -> new ArrayList<>(m.values()))); 

System.out.println(list2); // [2, 3, 1, 4, 5] 

注:如在評論中指出的霍爾格,它使用Map.values()而不是Map.keySet()創建很重要結果列表。這是因爲當使用m.put(e, e)時,如果在地圖中已經存在具有相同密鑰的條目,則舊值將被替換爲新值,但密鑰保持不變,即舊值。

+1

其他答案有一個小的差異。 'put'會將現有條目移到最前面,但不會替換關鍵實例。對於盒裝的小整數值,在相同的值始終具有相同的標識的情況下,這沒有什麼區別,但是在對象身份很重要的使用情況下,結果將是錯誤的。但這很容易解決;只需使用'values()'而不是'keySet()'。除此之外,向'LinkedHashMap',即'() - >新的LinkedHashMap (16,0.75f,true)'添加類型參數更簡單,而不是'Collector.of'。 – Holger

+1

[作品](http://ideone.com/ndx4Fi) – Holger

+0

@Holger好了,那麼這是IntelliJ的類型推理機制的一個缺陷。我報告了它,並且已經有報道。非常感謝你! –

相關問題