【问题标题】:Java - Concatenate Consecutive Elements in a StreamJava - 连接流中的连续元素
【发布时间】:2020-09-04 00:54:23
【问题描述】:

我正在尝试连接数组中的两个连续元素。我可以迭代地执行此操作,但我正在尝试学习 Java Streams,并认为这将是一个很好的练习。

如果我有一个字符串数组: String exampleArray[] = ["a1", "junk", "a2", "b1", "junk", "b2", "c1", "junk", "junk", "junk", "c2", "d1", "junk", "d2", "junk-n"]

我想得到: ["a1 - a2", "b1 - b2", "c1 - c2", "d1 - d2"] 作为输出。

我试过了:

Arrays.asList(exampleArray)
    .stream()
    .filter(s -> s.length() > 0)   // gets rid of blanks
    .filter(s -> !s.contains("junk"))
    .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 2))
    .values();

这会返回一个Collection<List<String>>,比如[ [a1, a2], [b1, b2], [c1, c2], [d1, d2] ]

但我不知道怎么去:["a1 - a2", "b1 - b2", "c1 - c2", "d1 - d2"]

感谢任何帮助!

【问题讨论】:

  • 为什么不是groupBy字符串的第一个字符?你怎么除以2 后还有这么多组?
  • 我的数据没有 'a1', 'a2' - 这只是一个例子

标签: java java-stream concatenation


【解决方案1】:

你快到了。你已经有了这些对,你现在要做的就是用中间的“-”将它们粉碎成一个字符串。

试试这个:

Arrays.stream(exampleArray)
                .filter(s -> s.length() > 0)   // gets rid of blanks
                .filter(s -> !s.contains("junk"))
                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 2))
                .values()
                .stream()                        //stream the pairs
                .map(l -> String.join("-", l))   //and put a "-" between them & into a string
                .collect(Collectors.toList())    //collect all your joined String

【讨论】:

  • 谢谢!我只是没想过在内部列表中的所有字符串上使用.map
  • @banncee,np。每当您想要或需要“转换”、“转换”或从一种类型转换为另一种类型时,请考虑“映射”。
【解决方案2】:

Collectors.groupingBy 有一个重载方法,您可以在其中将结果传递给下游收集器。事实上,默认情况下它使用了 toList 收集器,所以你得到了 List。您可以使用 joinBy 来连接字符串。

.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 2
       , Collectors.joining(" - ")))

结果是

[a1-a2, b1-b2, c1-c2, d1-d2]

代码

public static void main(String[] args) {
    String exampleArray[] = new String[] {"a1", "junk", "a2", "b1", "junk", "b2", "c1", "junk", "junk", "junk", "c2", "d1", "junk", "d2", "junk-n"};
    AtomicInteger counter = new AtomicInteger(0);
    Collection<String> ans = (Arrays.asList(exampleArray)
            .stream()
            .filter(s -> s.length() > 0)   // gets rid of blanks
            .filter(s -> !s.contains("junk"))
            .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 2, Collectors.joining(" - ")))
            .values());

    System.out.println(ans);
}

【讨论】:

  • 这会导致类型问题; The method collect(Supplier&lt;R&gt;, BiConsumer&lt;R,? super String&gt;, BiConsumer&lt;R,R&gt;) in the type Stream&lt;String&gt; is not applicable for the arguments (Collector&lt;Object,?,Map&lt;Object,List&lt;Object&gt;&gt;&gt;, Collector&lt;CharSequence,capture#2-of ?,String&gt;)
  • @banncee 这有点奇怪,因为它对我有用,没有任何问题。我用完整的代码更新了答案。你做了什么不同的事情吗?
  • 这对我也有用,我也不确定发生了什么。诚然,这比我的答案和我在真实应用程序中使用的更清晰、更简洁。当我回答时,我的思考过程更多的是在“循序渐进”的思维框架中,因此更容易解释“链”步骤。
【解决方案3】:

实现此输出的简单方法是:

String a[] = {"a1", "junk", "a2", "b1", "junk", "b2", "c1", "junk", "junk", "junk", "c2", "d1", "junk", "d2", "junk-n"};

    Arrays.parallelSort(a); //sorting the array from a to z
    
    List<String> output = new ArrayList<>();
    
    for (int i = 0; i < a.length - 1; i++) {
        
        if(a[i].matches(".*\\d.*")) //verifying if have a number in string
           output.add(a[i] + " - " + a[++i]);
        
    }
    
    System.out.println(output); //["a1 - a2", "b1 - b2", "c1 - c2", "d1 - d2"]

【讨论】:

  • 对不起,我应该澄清一下 - 数据仅用于说明目的。通常,它们将是随机文本。
猜你喜欢
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多