如何在Java 8中迭代Map以获得一个由重复字符键组成的字符串



我有一个Map如下所示:

Map<Character, Integer> map = new LinkedHashMap<Character, Integer>();
map.put('c', 5);
map.put('f', 2);
map.put('r', 1);
map.put('D', 3);

我需要得到的输出:

cccccffrDDD

我可以在正常进程中做,但我想在Java 8中做。你能分享一些如何做到这一点的提示吗?

这是你需要的吗?

Map<Character, Integer> map = new LinkedHashMap<Character, Integer>();
map.put('c',5);
map.put('f', 2);
map.put('r', 1);
map.put('D', 3);
StringBuilder sb = new StringBuilder();
map.forEach((k,v)->{
sb.append(String.valueOf(k).repeat(v));
});
System.out.print(sb);

注意repeat方法只在Java 11以上可用。

Java 1.8版本

StringBuilder sb = new StringBuilder();
map.forEach((k,v)->{
for(int i=0; i<v; i++) {
sb.append(k);
}
});
System.out.print(sb);

您可以使用forEach()和StringBuilder来组合。

StringBuilder sb = new StringBuilder(); 
map.forEach((k,v) -> { 
for (int i = 0; i < v; i++) { 
sb.append(k); 
} 
}); 

这里有一些关于如何使用Java 8流解决这个问题的想法。

总体思路:

  • 创建映射条目流;
  • 生成基于每个条目的单字母字符串流,并使用内置收集器joining()合并它们;
  • joining()收集器进行收集,得到最终结果。
String joinedLetters = map.entrySet().stream()
.map(entry -> Stream.generate(() -> String.valueOf(entry.getKey()))
.limit(entry.getValue())
.collect(Collectors.joining()))
.collect(Collectors.joining());

另一种方法:

  • 创建条目流
  • 使用Collections.nCopies()创建轻量级字符串列表;
  • 使用静态方法String.join()将每个列表转换为String;
  • 使用joining()收集器组合字符串。
String joinedLetters = map.entrySet().stream()
.map(entry -> Collections.nCopies(entry.getValue(), String.valueOf(entry.getKey())))
.map(list -> String.join("", list))
.collect(Collectors.joining());

使用这个链接来玩在线演示

您可以流式传输map的条目集,并使用String.repeat(int count)(在Java 11中引入)将键的值作为因子打印出来,可能如下所示:

public static void main(String[] args) {    
Map<Character, Integer> map = new LinkedHashMap<Character, Integer>();
map.put('c',5);
map.put('f', 2);
map.put('r', 1);
map.put('D', 3);
// stream the set of entries and repeat the (String version of the) key value-times
map.entrySet().forEach(e -> System.out.print(e.getKey().toString().repeat(e.getValue())));
}

这个打印

cccccffrDDD

当您使用没有String.repeat(…)方法的Java 8时,您可以使用

String result = map.entrySet().stream()
.map(e -> {
char[] array = new char[e.getValue()];
Arrays.fill(array, e.getKey());
return CharBuffer.wrap(array);
})
.collect(Collectors.joining());

或使用自定义收集器:

String result = map.entrySet().stream()
.collect(Collector.of(
StringBuilder::new,
(sb, e) -> { for(int i = e.getValue(); i > 0; i--) sb.append(e.getKey()); },
StringBuilder::append,
StringBuilder::toString));

如上所述,可以使用lambda表达式构建字符串,如下所示。

StringBuilder output = new StringBuilder();
map.forEach((k, v) -> {
for (int i = 0; i < v; i++) {
output.append(k);
}
});

或者你可以用IntStreams替换标准。

StringBuilder output = new StringBuilder();
map.forEach((k, v) -> IntStream.range(0, v).forEach(i -> b.append(k)));

最新更新