如何使用Streams在Java8中将HashMap转换为K/V字符串

如何使用Streams在Java8中将HashMap转换为K/V字符串,java,hashmap,java-8,java-stream,Java,Hashmap,Java 8,Java Stream,我想尽快创建我的HashMap m的键值对字符串 我试过: StringBuffer buf = new StringBuffer(); buf.append("["); for (String key : m.keySet()) { buf.append(key); buf.append("="); buf.append(m.get(key)); buf.append(";"); } buf.append("]"); 使用Java8,我尝试了: m.entrySet(

我想尽快创建我的
HashMap m
的键值对字符串

我试过:

StringBuffer buf = new StringBuffer();
buf.append("[");
for (String key : m.keySet()) {
   buf.append(key);
   buf.append("=");
   buf.append(m.get(key));
   buf.append(";");
}
buf.append("]");
使用Java8,我尝试了:

m.entrySet().stream()
            .map(entry -> entry.getKey() + " = " + entry.getValue())
            .collect(Collectors.joining("; " , "[" , "]"));
有没有更快更好的代码可以做到这一点?
在映射函数中附加键和值似乎代价高昂,不是吗?

使用StringBuilder而不是buffer

Javadoc=>classstringbuffer

“通常应优先使用StringBuilder类,因为它支持所有相同的操作,但速度更快,因为它不执行同步。”

@Test
public void testMapPrint(){
Map Map=newhashmap();
地图放置(“a”、“b”);
地图放置(“c”、“d”);
map.entrySet().stream()
.forEach(entry->System.out.println(entry.getKey()+”:“+entry.getValue());
}
(注意,我省略了导入。)

就像我说的:


在这种情况下,我不会担心性能,除非它是系统的关键部分,并且通过使用探查器或类似工具指出它是一个瓶颈。如果您以前没有这样做过,并且您认为这段代码不是最优的,那么I̶k̶n̶o̶w̶t̶h̶a̶t̶也许您错了,应该先测试它


当您分析这两种方法时,哪种方法运行得比另一种更快?速度有多快?在这种情况下,我不会担心性能,除非它是系统的一个关键部分,并且使用探查器或类似工具指出它是一个瓶颈。如果您以前没有这样做过,并且您认为这段代码不是最优的,那么I̶k̶n̶o̶w̶t̶h̶a̶t̶,可能您错了,应该先测试它。FWIW-对于这一点来说,
m.toString()
的结果可能足够接近。您是否尝试过使用并行流?请注意,在JDK 9
stringer
(这是
收集器的底层类。加入
)经过了优化,因此流实现的速度将比JDK 8快20-25%(尽管仍然不如naive快)。它比流的解决方案快吗?两者可以结合使用吗?虽然对第一段代码使用StringBuilder可能比StringBuffer快,但正如@LuiggiMendoza指出的,问题是第二段代码的速度。对于读者,编译器在第二种情况下为是一段代码:
entry.getKey()+“=”+entry.getValue())
在每次迭代中,因此不需要使用另一个
StringBuilder
。而
Collectors#joining
将使用
StringJoiner
在幕后使用
StringBuilder
,我想使用
StringBuilder
根本没有什么真正的改进。@Luiggmendoza,顺便说一句,在JDK 9中,它不再使用
StringBuilder
。将每一对单独打印到控制台需要大量时间。在字符串{Builder,Builder }中收集所有的东西,然后打印它最快。如果你想进入微标杆,你也应该考虑字符串生成器中的字符数组扩展的情况(它也很昂贵,默认为char(16)):如果你想直接打印一张地图,不需要
。只需使用
map.forEach((k,v)->System.out.println(k+“:”+v))OP的“Collectors.joining()”调用的分隔符、前缀和后缀顺序错误。您的解决方案解决了这个问题。请注意,虽然
Entry.toString()
通常返回
key=value
,但接口并不明确要求它,因此您可能会遇到返回其他内容的映射实现。我更喜欢像问题中那样的显式连接。我已经看过了
Entry
接口。我无法对任何声明
toString
进行罚款。您能解释一下如何定义
Entry::toString()
?另一件事,只有
Entry::toString
无法解决。我需要做
Map.Entry::toString()
@seal
toString()
是由
java.lang.Object
声明的,所以它被所有东西继承。如果执行
导入java.util.Map.Entry
,则可以直接使用
Entry::toString
。@seal
@Test
public void testMapPrint() {
    Map<String, String> map = new HashMap<>();
    map.put("a", "b");
    map.put("c", "d");

    map.entrySet().stream()
            .forEach(entry -> System.out.println(entry.getKey() + ":" + entry.getValue()));
}
map -> map.entrySet().stream().map(Entry::toString).collect(joining(";", "[", "]"))