[英]Streams use for map computation from list with counter
我有以下 for 循環,我想用一個簡單的 Java 8 stream 語句替換它:
List<String> words = new ArrayList<>("a", "b", "c");
Map<String, Long> wordToNumber = new LinkedHashMap<>();
Long index = 1L;
for (String word : words) {
wordToNumber.put(word, index++);
}
我基本上想要每個單詞的排序 map (按插入順序)到它的編號(在每個 for 循環中遞增 1),但如果可能的話,使用 Java 8 個流做得更簡單。
以下應該工作(雖然不清楚為什么需要Long
因為List
的大小是int
)
Map<String, Long> map = IntStream.range(0, words.size())
.boxed().collect(Collectors.toMap(words::get, Long::valueOf));
如果words
列表中沒有重復項,則上面的代碼有效。
如果可能出現重復單詞,則需要將合並 function 提供給 select,該索引應存儲在 map 中(第一個或最后一個)
Map<String, Long> map = IntStream.range(0, words.size())
.boxed().collect(
Collectors.toMap(words::get, Long::valueOf,
(w1, w2) -> w2, // keep the index of the last word as in the initial code
LinkedHashMap::new // keep insertion order
));
同樣,map 可以通過流式傳輸words
和使用外部變量來增加索引來構建(可以使用AtomicLong
和getAndIncrement()
代替long[]
):
long[] index = {1L};
Map<String, Long> map = words.stream()
.collect(
Collectors.toMap(word -> word, word -> index[0]++,
(w1, w2) -> w2, // keep the index of the last word
LinkedHashMap::new // keep insertion order
));
Map<String, Long> wordToNumber =
IntStream.range(0, words.size())
.boxed()
.collect(Collectors.toMap(
words::get,
x -> Long.valueOf(x) + 1,
(left, right) -> { throw new RuntimeException();},
LinkedHashMap::new
));
您可以替換它(left, right) -> { throw new RuntimeException();}
取決於您要如何合並兩個元素。
稍微不同的解決方案。 Integer::max
是合並 function 如果同一個單詞出現兩次就會被調用。 在這種情況下,它選擇最后一個 position ,因為這實際上是問題中的代碼示例所做的。
@Test
public void testWordPosition() {
List<String> words = Arrays.asList("a", "b", "c", "b");
AtomicInteger index = new AtomicInteger();
Map<String, Integer> map = words.stream()
.map(w -> new AbstractMap.SimpleEntry<>(w, index.incrementAndGet()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max));
System.out.println(map);
}
Output:
{a=1, b=4, c=3}
編輯:
在評論中結合 Alex 的建議,它變成:
@Test
public void testWordPosition() {
List<String> words = Arrays.asList("a", "b", "c", "b");
AtomicLong index = new AtomicLong();
Map<String, Long> map = words.stream()
.collect(Collectors.toMap(w -> w, w -> index.incrementAndGet(), Long::max));
System.out.println(map);
}
我基本上想要每個單詞的排序 map (按插入順序)到它的編號(在每個 for 循環中遞增 1),但如果可能的話,使用 Java 8 個流做得更簡單。
您可以使用以下Stream
簡潔地做到這一點:
AtomicLong index = new AtomicLong(1);
words.stream().forEach(word -> wordToNumber.put(word, index.getAndIncrement()));
就個人而言,我認為要么
Map<String, Long> wordToNumber = new LinkedHashMap<>();
for(int i = 0; i < words.size(); i++){
wordToNumber.put(words.get(i), (long) (i + 1));
}
或者
Map<String, Long> wordToNumber = new LinkedHashMap<>();
for (String word : words) {
wordToNumber.put(word, index++);
}
足夠簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.