Java 如何在比赛后使用流查找项目?
使用Java streams,很容易找到与给定属性匹配的元素。Java 如何在比赛后使用流查找项目?,java,regex,lambda,Java,Regex,Lambda,使用Java streams,很容易找到与给定属性匹配的元素。 例如: String b = Stream.of("a1","b2","c3") .filter(s -> s.matches("b.*")) .findFirst().get(); System.out.println("b = " + b); 生产: b=b2 然而,人们通常希望在匹配后立即获得一个或多个值,而不是匹配本身。我只知道如何使用旧的循环方式来实现这一点 String args[
例如:
String b = Stream.of("a1","b2","c3")
.filter(s -> s.matches("b.*"))
.findFirst().get();
System.out.println("b = " + b);
生产:b=b2 然而,人们通常希望在匹配后立即获得一个或多个值,而不是匹配本身。我只知道如何使用旧的循环方式来实现这一点
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);
String args[]={“-a”、“1”、“b”、“2”、“c”、“3”};
字符串结果=”;
for(int i=0;i
将产生:结果=2 有没有一种干净的方式来处理Java8流?例如,给定上面的数组,将result设置为“2”,并谓词
s->s.matches(“-b.*)
)
如果您可以获取下一个值,那么在匹配另一个谓词之前,也可以获取下一个N值或所有值的列表/数组,例如
s->s.matches(“-c.*”)
对于在使用somPair
或Tuple
类之后直接需要值的情况
String b = Stream.of(Pair.of("-a","1"),Pair.of("-b","2"),Pair.of("-c","3"))
.filter(p -> p.first.matches("-b.*"))
.map(p -> p.second)
.findFirst().get();
我不能说下面的方法是有效的,但它遵循了一种易于应用的模式。(不过,在真正的函数式语言中,在添加过滤器时,这可能是有效的。) 首先从字符串流中收集
[[-c,3],-b,2],-a,1]]
List<List<String>> optionLists = Stream.of("-a","1","-b","2","-c","3")
.collect(ArrayList<List<String>>::new,
(lists, arg) -> {
if (arg.startsWith("-")) {
List<String> list = new LinkedList<>();
list.add(arg);
lists.add(0, list);
} else {
List<String> list = lists.get(0);
list.add(arg);
}
},
List::addAll);
System.out.println(optionLists);
List optionlist=Stream.of(“-a”、“1”、“b”、“2”、“c”、“3”)
.collect(数组列表::新建,
(列表,arg)->{
if(参数开始时带(“-”)){
列表=新建LinkedList();
列表。添加(arg);
列表。添加(0,列表);
}否则{
List=lists.get(0);
列表。添加(arg);
}
},
列表::addAll);
System.out.println(选项列表);
然后你可以把它放在所有选项的地图上
List bargs=optionList.stream()
.collect(收集器.toMap(lst->lst.get)(0),
lst->lst.subList(1,lst.size()).get(“-b”);
System.out.println(“For-b:+bargs”);
我通过这篇博文找到了它:名为jOOL的库有一个Github链接
和Maven central信息:
该示例的代码为:
import org.jooq.lambda.Seq;
据我所知,似乎没有一种简单的方法可以做到这一点,其中的很多原因都源于Java的Stream API缺乏获取流元素索引的功能以及将流压缩在一起的能力 如果我们能够获得流中某个元素的索引,然后简单地使用.skip()函数和.limit(n)函数组合使用来丢弃包含所需匹配点的元素,然后将结果限制到接下来的n个元素,那么我们可以想象一个简单的问题解决方案 您可能想查看Protonpack,它是一个“针对Java 8的Streams实用程序库,提供takeWhile、skipWhile、zip和unfold”。使用此库,解决此问题的简单方法可能如下所示:
Stream<String> stringStream = Stream.of("-a","1","-b","2","-c","3");
Stream<String> nAfterMatch =
StreamUtils.skipWhile(stringStream, s -> !(s.matches("-b.*")))
.limit(n);
Stream-stringStream=Stream.of(“-a”、“1”、“b”、“2”、“c”、“3”);
流nAfterMatch=
StreamUtils.skipWhile(stringStream,s->!(s.matches(“-b.*)))
.限制(n);
这是一种使用流解决此问题所需的拆分器:
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; }
}
}
作为补充,本文介绍的拆分器通过依赖AbstractSpliterator
中的trySplit
的默认实现来支持并行性这可能是一种变通解决方案:
String[] args = {"-a","1","-b","2","-c","3"};
String b = IntStream.range(1, args.length)
.mapToObj(i -> new Pair<>(args[i-1], args[i]))
.filter(pp -> pp.getFirst().startsWith("-b"))
.findFirst().get().getSecond();
System.out.println("b = " + b);
//=> Output: b = 2
String[]args={“-a”、“1”、“b”、“2”、“c”、“3”};
字符串b=IntStream.range(1,args.length)
.mapToObj(i->新对(args[i-1],args[i]))
.filter(pp->pp.getFirst().startsWith(“-b”))
.findFirst().get().getSecond();
System.out.println(“b=“+b”);
//=>输出:b=2
.mapToObj
用于使用输入数组args
中的连续索引从args
数组中生成字符串值对 多亏了Java StreamstakeWhile
才有可能:
Stream<String> strings = Stream.of("a1","b2","c3");
final AtomicBoolean matchFound = new AtomicBoolean(false);
final AtomicReference<String> stringAfterMatch = new AtomicReference<>();
strings.takeWhile(string -> stringAfterMatch.get() == null).forEach(string -> {
if (matchFound.get()) {
stringAfterMatch.set(string);
}
if (string.matches("b.*")) {
matchFound.set(true);
}
});
String b = stringAfterMatch.get();
Stream strings=Stream.of(“a1”、“b2”、“c3”);
final AtomicBoolean matchFound=新的AtomicBoolean(false);
final AtomicReference stringAfterMatch=新的AtomicReference();
string.takeWhile(string->stringAfterMatch.get()==null).forEach(string->{
if(matchfind.get()){
stringAfterMatch.set(字符串);
}
if(string.matches(“b.*)){
matchFound.set(true);
}
});
字符串b=stringAfterMatch.get();
私有静态布尔值(字符串输入,字符串[]字){
Arrays.stream(words).allMatch(新谓词(){
@凌驾
公共布尔测试(字符串t){
if(输入包含(t))
计数器+=1;//添加全局计数器
//ExtensionUtils.keyWordHash.put(t,input);//或者您可以将字符串放入hashmap并稍后检索
返回输入。包含(t);
}
});
返回Arrays.stream(words).allMatch(input::contains);
}
我认为答案是否定的。我有理由相信,任何使用流的解决方案都会非常复杂,可读性也会受到影响。流是一个非常通用的工具,但你知道这样一句话:“当你有锤子时,一切看起来都像钉子”。但事实上,并不是所有的东西都是钉子。如果streams支持分区
操作(我使用Clojure的命名),这将很容易做到。这将允许您将其重新组织为一个成对的流。在拆分器级别有一种方法可以做到这一点(我有代码),但对于您的情况来说可能不值得。您正在寻找的是一个“转换”双工流,它会发出自己的输出
partition(Stream.of("-a","1","-b","2","-c","3"), 2)
.filter(pair -> pair.get(0).equals("-b"))
.findFirst()
.map(pair -> pair.get(1))
.orElse("");
String[] args = {"-a","1","-b","2","-c","3"};
String b = IntStream.range(1, args.length)
.mapToObj(i -> new Pair<>(args[i-1], args[i]))
.filter(pp -> pp.getFirst().startsWith("-b"))
.findFirst().get().getSecond();
System.out.println("b = " + b);
//=> Output: b = 2
Stream<String> strings = Stream.of("a1","b2","c3");
final AtomicBoolean matchFound = new AtomicBoolean(false);
final AtomicReference<String> stringAfterMatch = new AtomicReference<>();
strings.takeWhile(string -> stringAfterMatch.get() == null).forEach(string -> {
if (matchFound.get()) {
stringAfterMatch.set(string);
}
if (string.matches("b.*")) {
matchFound.set(true);
}
});
String b = stringAfterMatch.get();
private static boolean containsWords(String input, String[] words) {
Arrays.stream(words).allMatch(new Predicate<String>() {
@Override
public boolean test(String t) {
if(input.contains(t))
counter+=1; //add a global counter
//ExtensionUtils.keyWordHash.put(t, input); // or you can put the strings to a hashmap and retrieve later
return input.contains(t);
}
});
return Arrays.stream(words).allMatch(input::contains);
}