【问题标题】:How to compare and operate two adjacent elements in one list using stream in Java?java - 如何使用Java中的流比较和操作一个列表中的两个相邻元素?
【发布时间】:2019-01-21 09:37:12
【问题描述】:

背景是我有两个字符串类型变量 str1 和 str2 作为输入。最后,我必须返回一个列表,其中包含 str1 的连续前缀,该前缀小于 str2 中的相关前缀。

我有这样的 Java 代码:

public List<Character> getPrefix(String str1, String str2) {
    int index = 0;
    List<Character> res = new ArrayList<>();
    //str1 = "1243"
    //str2 = "2324"
    // The answer will be "12".

    while (index < str1.length() && index < str2.length() && str1.charAt(index) <= str2.charAt(index)) {
        res.add(str1.charAt(index));
        index++;
    } 

    return res;
}
//the return type could either be List<String> or List<Character>

我被要求在流中转换这段代码,而不使用 while 或 for 循环,只是在流方法中。我打算像这样转换这段代码

List<String> list = new ArrayList<>();
list.add(str1);
list.add(str2);
List<String> res = list.stream()
.filter()
.reduce();

我发现filter() 方法可以选择与给定谓词匹配的元素,reduce() 方法可以使用标识和累加器来获得一个最终结果。

但我发现我既没有办法操作一个列表中的两个相邻元素,也没有办法获得一个指针来比较和遍历列表中每个元素中的每个字符(该元素是字符串类型)。

那么有什么方法可以操作一个列表中的两个相邻元素,以便比较它们在同一位置的字符。

【问题讨论】:

    标签: java java-8 java-stream


    【解决方案1】:

    你可以:

    1. 生成索引流
    2. 使用索引获取两个字符串的字符
    3. 在有效时选择字符

      // The magic
      public static List<Character> getPrefix(String str1, String str2) {
      
          return IntStream
              .range(0, Math.min(str1.length(), str2.length()))
              .mapToObj(i -> new char[] { str1.charAt(i), str2.charAt(i) })
              .takeWhile(a -> a[0] < a[1])
              .map(a -> a[0])
              .collect(Collectors.toList());
      
      }
      

    【讨论】:

      【解决方案2】:

      看看代码,也许这就是你想要的。 仍然可以进一步增强它并且不能解决第一个字符串以大于第二个的值开始的情况。这也可以实现,但需要额外的工作。 (不能一次性完成,因为供应商消耗了一个元素来进行链接 dropWhile 和 takeWhile 所需的检查)。 简单地说,通过供应商,您可以将流中的元素与其他数据结构中的元素进行比较。

      import java.util.LinkedList;
      import java.util.function.Supplier;
      import java.util.stream.Collectors;
      
      public class Pre1 {
      
          public static void main(String[] args) {
              System.out.println(new Pre1().getPre("1234", "2315"));
              System.out.println(new Pre1().getPre("941234", "712315"));
              System.out.println(new Pre1().getPre("2345", "341"));   
          }
      
          public String getPre(String s1, String s2) {
              //second list is used as supplier
              LinkedList<Integer> l2 = s2.chars().boxed()
                  .map(t->Character.getNumericValue(t))
                  .collect(Collectors.toCollection(LinkedList<Integer>::new));
              //l2.forEach(System.out::println);
              Supplier<Integer> supplier = () -> {
              //   System.out.println(l2.peek());
                   return l2.isEmpty() ? 0 : l2.pollFirst();
              };
      
              return s1.chars().boxed()
                   .map(t->Character.getNumericValue(t))
                   .takeWhile(t->t<supplier.get())
                   .map(t->String.valueOf(t))
                   .collect(Collectors.joining());
          }
      }
      

      输出

      12
      nothing 
      23
      

      【讨论】:

      • 很好的解决方案,谢谢您的回答。
      猜你喜欢
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 2018-05-30
      • 2019-04-08
      • 1970-01-01
      • 2019-12-07
      相关资源
      最近更新 更多