java - 如何使用流在比赛结束后找到一件元素?

标签 java regex lambda

使用 Java 流很容易找到与给定属性匹配的元素。
如:

 String b = Stream.of("a1","b2","c3")
     .filter(s -> s.matches("b.*"))
     .findFirst().get();
 System.out.println("b = " + b);

产出:
b=b2

然而,人们通常希望在匹配后立即获得一个或多个值,而不是匹配本身。我只知道如何使用老式的 for 循环来做到这一点。

    String args[] = {"-a","1","-b","2","-c","3"};
    String result = "";
    for (int i = 0; i < args.length-1; i++) {
        String arg = args[i];
        if(arg.matches("-b.*")) {
            result= args[i+1];
            break;
        }
    }
    System.out.println("result = " + result);

将产生:
结果=2

Java 8 Streams 是否有一种干净的方法来做到这一点?例如,在给定上面的数组和谓词 s -> s.matches("-b.*") 的情况下将结果设置为“2”。

如果您可以获得下一个值,那么在匹配另一个谓词(例如 s -> s.matches)之前,还可以获取下一个 N 值或所有值的列表/数组也会很有用("-c.*").

最佳答案

这是用流解决这个问题所需要的那种拆分器:

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class PartitioningSpliterator<E> extends AbstractSpliterator<List<E>>
{
  private final Spliterator<E> spliterator;
  private final int partitionSize;

  public PartitioningSpliterator(Spliterator<E> toWrap, int partitionSize) {
    super(toWrap.estimateSize(), toWrap.characteristics());
    if (partitionSize <= 0) throw new IllegalArgumentException(
        "Partition size must be positive, but was " + partitionSize);
    this.spliterator = toWrap;
    this.partitionSize = partitionSize;
  }

  public static <E> Stream<List<E>> partition(Stream<E> in, int size) {
    return StreamSupport.stream(new PartitioningSpliterator(in.spliterator(), size), false);
  }

  @Override public boolean tryAdvance(Consumer<? super List<E>> action) {
    final HoldingConsumer<E> holder = new HoldingConsumer<>();
    if (!spliterator.tryAdvance(holder)) return false;
    final ArrayList<E> partition = new ArrayList<>(partitionSize);
    int j = 0;
    do partition.add(holder.value); while (++j < partitionSize && spliterator.tryAdvance(holder));
    action.accept(partition);
    return true;
  }

  @Override public long estimateSize() {
    final long est = spliterator.estimateSize();
    return est == Long.MAX_VALUE? est
         : est / partitionSize + (est % partitionSize > 0? 1 : 0);
  }

  static final class HoldingConsumer<T> implements Consumer<T> {
    T value;
    @Override public void accept(T value) { this.value = value; }
  }
}

一旦你把它藏在项目的某个地方,你就可以说

partition(Stream.of("-a","1","-b","2","-c","3"), 2)
      .filter(pair -> pair.get(0).equals("-b"))
      .findFirst()
      .map(pair -> pair.get(1))
      .orElse("");

作为一个方面,所提出的拆分器依赖于 AbstractSpliteratortrySplit 的默认实现来支持并行性。

关于java - 如何使用流在比赛结束后找到一件元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31789279/

相关文章:

java - mono.zip 功能未按预期工作

regex - 有没有办法嵌套 sed 替换?

javascript - 在 Lambda 的 node8.10 中获取 API 调用导致 Promise <pending> 和 undefined

c++ - 在自定义通用容器中查找元素(使用 lambda 进行对象转换)C++

c++ - 将编译器生成的C++ lambda名称更改为易于阅读的名称

java - Jsoup Element.val() 解码编码的 html 内容

java - eclipse 中的可执行 jar 无法使用包内的图像...有时

java.lang.IllegalArgumentException : Empty values

c# - 正则表达式。仅替换正则表达式的一部分

Python - 使用正则表达式将数字和字母拆分为子字符串