java - 如何将带有条件的 for 迭代转换为 Java 8 流

标签 java java-8 java-stream

目前,我有这个方法,我想将其转换为 Java 8 流样式(顺便说一句,我很少使用这个 API,这就是这个小练习的目的):

private static Map<Integer, List<String>> splitByWords(List<String> list) {
   for (int i = 0; i < list.size(); i++) { 
        if(list.get(i).length() > 30 && list.get(i).contains("-")) {
            mapOfElements.put(i, Arrays.stream(list.get(i).split("-")).collect(Collectors.toList()));
        } else if(list.get(i).length() > 30) {
            mapOfElements.put(i, Arrays.asList(new String[]{list.get(i)}));
        } else {
            mapOfElements.put(i, Arrays.asList(new String[]{list.get(i) + "|"}));
        }
   }

   return mapOfElements;
}

到目前为止,这是我得到的:

private static Map<Integer, List<String>> splitByWords(List<String> list) {
   Map<Integer, List<String>> mapOfElements = new HashMap<>();
   IntStream.range(0, list.size())
        .filter(i-> list.get(i).length() > 30 && list.get(i).contains("-"))
        .boxed()
        .map(i-> mapOfElements.put(i, Arrays.stream(list.get(i).split("-")).collect(Collectors.toList())));

//Copy/paste the above code twice, just changing the filter() and map() functions?

以“老式”的方式,我只需要一个for 迭代来完成我需要的关于我的条件的所有事情。有没有一种方法可以使用 Stream API 来实现,或者,如果我想坚持下去,我必须重复上面的代码,只是改变 filter() 和 map() 条件,因此有三个 for 迭代?

最佳答案

当前使用 for 循环的解决方案看起来不错。由于只需区分三种情况,因此无需概括处理。

如果有更多情况需要区分,那么重构代码就有意义了。我的方法是明确定义不同的条件及其相应的字符串处理。让我使用问题中的代码对其进行解释。

首先,我使用枚举定义了不同的条件。

  public enum StringClassification {
    CONTAINS_HYPHEN, LENGTH_GT_30, DEFAULT;

    public static StringClassification classify(String s) {
      if (s.length() > 30 && s.contains("-")) {
        return StringClassification.CONTAINS_HYPHEN;
      } else if (s.length() > 30) {
        return StringClassification.LENGTH_GT_30;
      } else {
        return StringClassification.DEFAULT;
      }
    }
  }

使用这个枚举我定义了相应的字符串处理器:

  private static final Map<StringClassification, Function<String, List<String>>> PROCESSORS;
  static {
    PROCESSORS = new EnumMap<>(StringClassification.class);
    PROCESSORS.put(StringClassification.CONTAINS_HYPHEN, l -> Arrays.stream(l.split("-")).collect(Collectors.toList()));
    PROCESSORS.put(StringClassification.LENGTH_GT_30, l -> Arrays.asList(new String[] { l }));
    PROCESSORS.put(StringClassification.DEFAULT, l -> Arrays.asList(new String[] { l + "|" }));
  }

基于此,我可以使用请求的 IntStream 进行整个处理:

  private static Map<Integer, List<String>> splitByWords(List<String> list) {
    return IntStream.range(0, list.size()).boxed()
      .collect(Collectors.toMap(Function.identity(), i -> PROCESSORS.get(StringClassification.classify(list.get(i))).apply(list.get(i))));
  }

该方法是为字符串检索适当的 StringClassification然后依次对应字符串处理器。字符串处理器正在实现 strategy pattern通过提供 Function<String, List<String>>映射 StringList<String>根据StringClassification .

一个简单的例子:

  public static void main(String[] args) {
    List<String> list = Arrays.asList("123",
      "1-2",
      "0987654321098765432109876543211",
      "098765432109876543210987654321a-b-c");
    System.out.println(splitByWords(list));
  }

输出是:

{0=[123|], 1=[1-2|], 2=[0987654321098765432109876543211], 3=[098765432109876543210987654321a, b, c]}

这使得添加或删除条件和字符串处理器变得容易。

关于java - 如何将带有条件的 for 迭代转换为 Java 8 流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52170415/

相关文章:

Java - Jboss 部署错误

java - 如果使用Java 8 Streams列表为空,则返回默认列表?

Java 8 Stream比较两个对象的列表

java - 从java中的二维数组流式传输

generics - lambda 与匿名类

java 8流从类型A的集合创建类型B的集合

java - 为什么 stream sorted() 无法推断我的类型?

java - 从 MainActivity 中的 onCreate() 启动另一个 Activity?

Java - 客户端的两个线程可以使用来自服务器的相同输入流吗?

java - Android前台服务onStartCommand不调用,仅onCreate调用