Java 如何打印由delimeter分隔的集合元素,而不创建大字符串?

Java 如何打印由delimeter分隔的集合元素,而不创建大字符串?,java,performance,java-8,Java,Performance,Java 8,非常相似的问题很接近,因为有人将其标记为问题的副本: 我认为生成一个表示集合的巨大字符串不是最好的方法。只需为我提供一个方法实现。谢谢。一般情况下,输入集合可能包含数千或数百万个元素,因此,比生成一个巨大的字符串对象更好的方法是直接打印到特定的输出流中 在最坏的情况下,它会导致超出堆内存,换句话说,方法/应用程序 在另一种情况下,无法将列表转换为字符串,因为它可能超出 这种方法允许您将由coma分隔的ArrayList元素直接打印到特定的打印流,例如System.out。 在我的转储实现中,我只

非常相似的问题很接近,因为有人将其标记为问题的副本:


我认为生成一个表示集合的巨大字符串不是最好的方法。只需为我提供一个方法实现。谢谢。

一般情况下,输入集合可能包含数千或数百万个元素,因此,比生成一个巨大的字符串对象更好的方法是直接打印到特定的输出流中

在最坏的情况下,它会导致超出堆内存,换句话说,方法/应用程序 在另一种情况下,无法将列表转换为字符串,因为它可能超出 这种方法允许您将由coma分隔的ArrayList元素直接打印到特定的打印流,例如System.out。 在我的转储实现中,我只是遍历集合。打印步骤是分开的,以避免为每个concat操作元素创建新字符串。toString+分隔符。 As@Pshemo通知流API方法将在最后一个元素之后打印分隔符

    public static <T> void nicePrint(final Collection<T> collection,
                                     final PrintStream printStream,
                                     final Optional<String> delimiter) {
        final Iterator<T> iterator = collection.iterator();
        while (iterator.hasNext()) {
            printStream.print(iterator.next());
            if (iterator.hasNext()) {
                delimiter.ifPresent(printStream::print);
            }
        }
    }

在一般情况下,输入集合可能包含数千或数百万个元素,因此比生成一个巨大的字符串对象更好的方法是直接打印到特定的输出流中

在最坏的情况下,它会导致超出堆内存,换句话说,方法/应用程序 在另一种情况下,无法将列表转换为字符串,因为它可能超出 这种方法允许您将由coma分隔的ArrayList元素直接打印到特定的打印流,例如System.out。 在我的转储实现中,我只是遍历集合。打印步骤是分开的,以避免为每个concat操作元素创建新字符串。toString+分隔符。 As@Pshemo通知流API方法将在最后一个元素之后打印分隔符

    public static <T> void nicePrint(final Collection<T> collection,
                                     final PrintStream printStream,
                                     final Optional<String> delimiter) {
        final Iterator<T> iterator = collection.iterator();
        while (iterator.hasNext()) {
            printStream.print(iterator.next());
            if (iterator.hasNext()) {
                delimiter.ifPresent(printStream::print);
            }
        }
    }

据我所知,你正在寻找类似Scala的能力

public static String mkString(Stream<String> s, String delimeter){
    return s.collect(Collectors.joining(delimeter));
}

System.out.println(print(Stream.of("1", "2", "3"), ", "));
//prints: 1, 2, 3

据我所知,你正在寻找类似Scala的能力

public static String mkString(Stream<String> s, String delimeter){
    return s.collect(Collectors.joining(delimeter));
}

System.out.println(print(Stream.of("1", "2", "3"), ", "));
//prints: 1, 2, 3

如果您只需要打印元素,并且担心只为打印而构建一个巨大的字符串,那么您仍然可以编写一个很好的旧for循环,该循环依次打印元素,后跟分隔符

我的意思是,新的Java8特性不会使这些构造不受欢迎

例如,如果需要,可以编写实用程序方法:

public static void printCollection(Collection<?> coll, String delimiter) {
    int size = coll.size();
    int i = 0;
    for(Object elem : coll) {
        System.out.print(elem);
        if(++i < size) {
            System.out.print(delimiter);
        }
    }
}
使用Java 8,您可能会使其更加紧凑:

public static void printCollection(Collection<?> coll, String delimiter) {
    //you can still avoid the map call and use two print statements in the forEach
    coll.stream().limit(coll.size()-1).map(o -> o+delimiter).forEach(System.out::print);
    coll.stream().skip(coll.size()-1).forEach(System.out::print);
}

如果您只需要打印元素,并且担心只为打印而构建一个巨大的字符串,那么您仍然可以编写一个很好的旧for循环,该循环依次打印元素,后跟分隔符

我的意思是,新的Java8特性不会使这些构造不受欢迎

例如,如果需要,可以编写实用程序方法:

public static void printCollection(Collection<?> coll, String delimiter) {
    int size = coll.size();
    int i = 0;
    for(Object elem : coll) {
        System.out.print(elem);
        if(++i < size) {
            System.out.print(delimiter);
        }
    }
}
使用Java 8,您可能会使其更加紧凑:

public static void printCollection(Collection<?> coll, String delimiter) {
    //you can still avoid the map call and use two print statements in the forEach
    coll.stream().limit(coll.size()-1).map(o -> o+delimiter).forEach(System.out::print);
    coll.stream().skip(coll.size()-1).forEach(System.out::print);
}

你有代码给我们看吗?forString value:collectionObject{String[]valArray=value.splitdelimeter;forString val:valArray{System.out.printlnval;}}}可以在CollectionOn上使用迭代器,如果你只需要打印元素,并且你担心为了打印而构建一个巨大的字符串,您仍然可以编写一个很好的旧for循环,它逐个打印元素,后跟分隔符。我的意思是,新的Java 8特性并没有使这些结构遭到反对…@Maroun Maroun我的答案是基于观点而不是事实?在我看来,OP在这里寻找的是实现技术,而不是关于什么更好或最好的观点。我已经投票决定重新打开。你有什么代码给我们看吗?forString value:collectionObject{String[]valArray=value.splitdelimeter;forString val:valArray{System.out.printlnval;}}可以在Collection上使用迭代器,如果你只需要打印元素,并且你担心为了打印而构建一个巨大的字符串,您仍然可以编写一个很好的旧for循环,它逐个打印元素,后跟分隔符。我的意思是,新的Java 8特性并没有使这些结构遭到反对…@Maroun Maroun我的答案是基于观点而不是事实?在我看来,OP在这里寻找的是实现技术,而不是关于什么更好或最好的观点。我投票赞成重新打开。问题是关于元素的集合,它还包括一个并没有getindex方法的集合。另外,我不认为使用Optional作为参数有什么意义。我喜欢使用它作为方法的结果,该方法可以返回null,可以表示值,或者缺少值,我们可能无法确定它与Map中的情况类似。如果ma中不存在键,或者键被赋值为null,则getkey可以返回null,但作为一个论据,它带来了太多的混乱。关于地图的观点与OP想要打印的集合无关,而是关于可选的使用,其主要目标是避免使用null。请阅读

它是Guava的可选版本,但也适用于Java8中添加的版本。在我看来,将分隔符作为字符串而不是可选的将更容易接受,如果您想避免打印它,您只需使用if!分隔符。这就是为什么我说,在我之前的评论中,我认为使用Optional作为参数没有意义。而且,因为在映射中使用Optional可能会有问题,所以我不应该在方法中使用Optional?我不知道它是从哪里来的,你们读过链接上的文章了吗?另外,若用户不想使用分隔符,那个么他可以传递,这比Optional.empty简单。即使是带有Joinder的Guava和带有String.join或StringJoinder的JDK也不使用Optional作为分隔符的参数。但让我们同意不同意。我们有权有自己的好恶。我从来没有说过你的答案是错的,我说的只是我的观点。无论如何,这里有一些简单的规则可以遵循:在方法中,首选Optional作为返回类型,避免它作为参数。原因很简单:使用Optional,如果返回的null表示正确的值,或者缺少像getfoo的null这样的正确值,那么您可以清楚地看到,这可能意味着foo是错误的参数,但也可能意味着foo是正确的,并且正确的结果实际上是null。但除了提供空安全性之外,可选作为参数也限制了您的使用,因为由于类型擦除,我们不能有fooOptional{bar}和fooOptional{baz}。问题是关于元素的集合,其中还包括不具有getindex方法的集合。另外,我不认为使用可选作为参数有什么意义。我喜欢使用它作为方法的结果,该方法可以返回null,可以表示值,或者缺少值,我们可能无法确定它与Map中的情况类似。如果ma中不存在键,或者键被赋值为null,则getkey可以返回null,但作为一个论据,它带来了太多的混乱。关于地图的观点与OP想要打印的集合无关,而是关于可选的使用,其主要目标是避免使用null。请阅读它是关于可选的从番石榴,但它也适用于一个添加在Java8。在我看来,将分隔符作为字符串而不是可选的将更容易接受,如果您想避免打印它,您只需使用if!分隔符。这就是为什么我说,在我之前的评论中,我认为使用Optional作为参数没有意义。而且,因为在映射中使用Optional可能会有问题,所以我不应该在方法中使用Optional?我不知道它是从哪里来的,你们读过链接上的文章了吗?另外,若用户不想使用分隔符,那个么他可以传递,这比Optional.empty简单。即使是带有Joinder的Guava和带有String.join或StringJoinder的JDK也不使用Optional作为分隔符的参数。但让我们同意不同意。我们有权有自己的好恶。我从来没有说过你的答案是错的,我说的只是我的观点。无论如何,这里有一些简单的规则可以遵循:在方法中,首选Optional作为返回类型,避免它作为参数。原因很简单:使用Optional,如果返回的null表示正确的值,或者缺少像getfoo的null这样的正确值,那么您可以清楚地看到,这可能意味着foo是错误的参数,但也可能意味着foo是正确的,并且正确的结果实际上是null。但是除了提供空安全性之外,可选作为参数也限制了您,因为由于类型擦除,我们不能有fooooptional{bar}和fooooptional{baz}。我认为OP担心生成一个只用于打印的潜在大字符串。我猜然后返回一个流,如:return s.mapx->x+delimeter?。如果你不想建立一个巨大的字符串,那么字符串流是有意义的。您检索并打印它,然后移动到下一个。我想然后会返回一个流,如:return s.mapx->x+delimeter,但这样即使在最后一个元素之后,您也会打印分隔符。@Jatin这样您就可以用分隔符在每个元素上生成额外的字符串object@kjkrol我完全理解。这在写答案的时候要清楚!我认为OP担心的是只为打印它而构建一个潜在的巨大字符串。我猜然后返回一个流,如:returns s.mapx->x+delimeter?。如果你不想建立一个巨大的字符串,那么字符串流是有意义的。您检索并打印它,然后移动到下一个。我想然后会返回一个流,如:return s.mapx->x+delimeter,但这样即使在最后一个元素之后,您也会打印分隔符。@Jatin这样您就可以用分隔符在每个元素上生成额外的字符串object@kjkrol我完全理解。这在写答案的时候要清楚!我不明白的是:如果有一个庞大的字符串是一个问题,那么拥有一个庞大的收藏应该是一个更大的问题。如果一个人可以容纳这么大的收藏,那么我认为没有必要从中生成一个字符串。@Jatin可能吧,但是如果你有一个巨大的收藏并且需要打印它的内容,我认为最好
单独打印每个元素,而不是将它们的内容连接到后面打印的字符串中。你提出的观点是相关的,但这是另一个问题,依我看,是的。非常同意:。关于java 8解决方案:是的,让我们迭代流两次@老实说,我不知道确切的复杂性,但是如果你想知道哪种方法更快,你仍然可以进行适当的测量。此外,doc说skip是顺序管道上的一种廉价操作,如果我没有弄错的话,那么如果底层流的大小合适的话,将有一些改进使其成为一种固定时间操作。所以我不确定否决票是否合理。我不明白的是:如果有一个巨大的字符串是一个问题,那么有一个巨大的集合应该是一个更大的问题。如果一个人可以容纳如此大的集合,那么我认为没有必要从中生成一个字符串。@Jatin可能是这样,但是如果你有一个巨大的集合,并且需要打印它的内容,我认为最好是单独打印每个元素,而不是将它们的内容连接成一个字符串,然后再打印。你提出的观点是相关的,但这是另一个问题,依我看,是的。非常同意:。关于java 8解决方案:是的,让我们迭代流两次@老实说,我不知道确切的复杂性,但是如果你想知道哪种方法更快,你仍然可以进行适当的测量。此外,doc说skip是顺序管道上的一种廉价操作,如果我没有弄错的话,那么如果底层流的大小合适的话,将有一些改进使其成为一种固定时间操作。因此,我不确定否决票是否合理。