Java 用极限连接字符串

Java 用极限连接字符串,java,java-8,java-stream,Java,Java 8,Java Stream,仅使用标准Java库,什么是一种简单的机制来将字符串连接到某个限制,并在限制导致字符串变短时附加省略号 效率是需要的。连接所有字符串,然后使用String.substring()可能会消耗过多的内存和时间。可以在Java8流管道中使用的机制更可取,这样超过限制的字符串甚至可能永远不会被创建 出于我的目的,我很乐意接受以下两种形式的限制: 要加入的最大字符串数 结果中的最大字符数,包括任何分隔符 例如,这是使用标准库在Java8中强制最大数量的连接字符串的一种方法。有没有更简单的方法 fina

仅使用标准Java库,什么是一种简单的机制来将字符串连接到某个限制,并在限制导致字符串变短时附加省略号

效率是需要的。连接所有字符串,然后使用
String.substring()
可能会消耗过多的内存和时间。可以在Java8流管道中使用的机制更可取,这样超过限制的字符串甚至可能永远不会被创建

出于我的目的,我很乐意接受以下两种形式的限制:

  • 要加入的最大字符串数
  • 结果中的最大字符数,包括任何分隔符
例如,这是使用标准库在Java8中强制最大数量的连接字符串的一种方法。有没有更简单的方法

final int LIMIT = 8;

Set<String> mySet = ...;
String s = mySet.stream().limit( LIMIT ).collect( Collectors.joining(", "));
if ( LIMIT < mySet.size()) {
    s += ", ...";
}
final int LIMIT=8;
设置mySet=。。。;
字符串s=mySet.stream().limit(limit).collect(collector.joining(“,”);
如果(限制
仅使用标准Java库

我不相信里面有任何东西能满足你的要求


你需要自己写。它不会那么复杂,所以我不明白为什么编写自己的收集器会成为一个问题。

您可以为此编写自定义收集器。这是基于:

private静态收集器limitingJoin(字符串分隔符、整数限制、字符串省略号){
返回收集器(
ArrayList::新,
(l,e)->{
如果(l.尺寸()<限制)l.添加(e);
否则如果(l.size()==限制)l.add(省略号);
},
(l1,l2)->{
addAll(l2.subList(0,Math.min(l2.size(),Math.max(0,limit-l1.size())));
如果(l1.size()==limit)l1.add(省略号);
返回l1;
},
l->String.join(分隔符,l)
);
}
在这段代码中,我们保留了所有遇到的字符串的
ArrayList
。当一个元素被接受时,当前列表的大小将根据限制进行测试:严格小于它,添加该元素;等于它时,添加省略号。合并器部分也是如此,这有点棘手,因为我们需要正确处理子列表的大小,以避免超出限制。最后,finisher只是将该列表与给定的分隔符连接起来

此实现适用于并行流。它将保留流的头部元素。注意,即使在达到限制后没有添加任何元素,它也会消耗流中的所有元素

工作示例:

List<String> list = Arrays.asList("foo", "bar", "baz");
System.out.println(list.stream().collect(limitingJoin(", ", 2, "..."))); // prints "foo, bar, ..."
List List=Arrays.asList(“foo”、“bar”、“baz”);
System.out.println(list.stream().collect(limitingJoin(“,”,2,“…”));//打印“foo,bar,…”

虽然使用第三方代码不是询问者的选择,但其他读者可能会接受。即使编写自定义收集器,您仍然有一个问题:整个输入都将被处理,因为标准收集器不能短路(特别是不可能处理无限流)。My library增强了收集器的概念,使创建短路收集器成为可能。收集器还可随时提供:

StreamEx.of(mySet).collect( 
    Joining.with(", ").ellipsis("...").maxChars(100).cutAfterDelimiter() );

结果保证不超过100个字符。可以使用不同的计数策略:您可以通过字符、代码点或字符集进行限制(组合Unicode字符将不被计数)。此外,您还可以在任意位置(“第一个条目,第二个en…”)或单词(“第一个条目,第二个…”)之后、分隔符(“第一个条目,…”)之后或分隔符(“第一个条目,第二个条目…”)之前剪切结果。它也适用于并行流,但在有序情况下可能效率不高。

我就想到了这一点。我可以
limit(limit+1)
只遍历流的一部分,但仍然允许自定义收集器知道已达到限制。我希望我错过了更简单的东西。限制字符串的数量对我来说似乎毫无意义。它应该限制结果的长度,这意味着
limit()
不是答案。在某些情况下确实如此。然而,我有一个例子,已知字符串是短的;字符的精确限制是不必要的;我只想包括整根弦,谢谢。如果需要,可以通过在
collect()
@andythonas Yes之前插入
limit(limit+1)
来避免消耗流中的所有元素。但是收集器本身并没有短路。+1用于很好地实现字符串连接数。joiner中的许多字符会更复杂。这个问题不是要求“推荐或查找书籍、工具、软件库、教程或其他非现场资源”
StreamEx.of(mySet).collect( 
    Joining.with(", ").ellipsis("...").maxChars(100).cutAfterDelimiter() );