2014-02-25 106 views
4

Java 8中是否有任何方式在原始流上使用Stream::collect(Collector)在原始流上使用收集器

通常一個Stream<Integer>如實施例具有用於收集兩種方法:

然而IntStream僅具有用於收集一個方法:

現在,作爲示例代碼中,我有以下:

@Override 
public void run() { 
    result = LongStream.range(1, maximum).boxed() 
      .collect(Collectors.toMap(i -> i, i -> (int)Iterators.longStream(new CollatzGenerator(i)).count())) 
      .entrySet().stream() 
      .max(Comparator.comparingLong(Map.Entry::getValue)) 
      .get().getKey(); 
} 

正如你可以看到我第一個框的原語,以便能夠使用Collectors.方法。

有沒有什麼辦法可以使用原語,仍然有相同的代碼Collectors.toMap

+1

由於無論如何地圖將包含對象,有什麼可以獲得? –

回答

4

由於Map是通用接口,因此無法在沒有裝箱的情況下創建Map。然而,當你想要創建另一個流(只有兩個值包含在Map.Entry中)時,將項目收集到Map是沒有意義的。你可以創建Map.Entry實例而不收集值:

LongStream.range(1, maximum) 
    .mapToObj(i->new AbstractMap.SimpleEntry<>(i, Iterators.longStream(new CollatzGenerator(i)).count())) 
    .max(Comparator.comparingLong(Map.Entry::getValue)) 
    .get().getKey(); 

這仍然自動裝箱,但一旦你在這一點上,你也能按自己創造一個合適的值保持一流擺脫Map.Entry的:

static final class TwoLongs { 
    final long key, value; 
    TwoLongs(long k, long v) { key=k; value=v; } 
    public long getKey() { return key; } 
    public long getValue() { return value; } 
} 

有了這個支持類,你可以處理你的數據,而無需拳擊long S:

LongStream.range(1, maximum) 
    .mapToObj(i->new TwoLongs(i, Iterators.longStream(new CollatzGenerator(i)).count())) 
    .max(Comparator.comparingLong(TwoLongs::getValue)) 
    .get().getKey(); 

嗯,它仍然是某種拳擊,但創建一個項目(TwoLongs實例)對象而不是三個(一個Map.Entry和兩個Long s)。

+0

這比它要複雜得多。 –

+0

你的意思是說,在Java 8中有一種更簡單的方法,或者應該有一種更簡單的方法,比如Java是提供元組還是更簡單的方法來生成有限的流? –

+0

@Stuart Marks:他指的是將第二個值的邏輯集成到「Comparator」函數中的可能性。因此,不需要映射到流內的一對* pair *,但缺點是「比較器」會比所需的更頻繁地計算值。因此,對於一個簡單的映射,它可以簡化代碼,但對於這種用例,不推薦。我想他因爲這個原因撤銷了他的答案。 – Holger

0
long result = LongStream.range(0, 9) 
     .mapToObj(i -> new long[]{i, i}) 
     .max(Comparator.comparingLong(pair -> pair[1])) 
     .get()[0];