我有以下课程:
public static class GenerateMetaAlert implements WindowFunction<Tuple2<String, Boolean>, Tuple2<String, Boolean>, Tuple, TimeWindow> {
@Override
public void apply(Tuple key, TimeWindow timeWindow, Iterable<Tuple2<String, Boolean>> iterable, Collector<Tuple2<String, Boolean>> collector) throws Exception {
//code
}
}
我要尝试的是,对于集合中的每个元素,在字段中是否存在其他具有相反值的东西。
一个例子:
Iterable: [<val1,val2>,<val3,val4>,<val5,val6>,...,<valx,valy>]
|| || || ||
elem1 elem2 elem3 elemn
我要测试的内容:
foreach(element)
if elem(i).f0 = elem(i+1).f0 then ...
if elem(i).f0 = elem(i+2).f0 then ...
<...>
if elem(i+1).f0 = elem(i+2).f0 then ...
<...>
if elem(n-1).f0 = elem(n).f0 then ...
我认为使用类似这样的方法是可能的:
Tuple2<String, Boolean> tupla = iterable.iterator().next();
iterable.iterator().forEachRemaining((e)->{
if ((e.f0 == tupla.f0) && (e.f1 != tupla.f1)) collector.collect(e);});
但是像我刚接触Java一样,我不知道如何以最佳方式做到这一点。
这是使用Apache Flink的Java程序的一部分:
.keyBy(0, 1)
.timeWindow(Time.seconds(60))
.apply(new GenerateMetaAlert())
测试:
使用以下代码:
public static class GenerateMetaAlert implements WindowFunction<Tuple2<String, Boolean>, Tuple2<String, Boolean>, Tuple, TimeWindow> {
@Override
public void apply(Tuple key, TimeWindow timeWindow, Iterable<Tuple2<String, Boolean>> iterable, Collector<Tuple2<String, Boolean>> collector) throws Exception {
System.out.println("key: " +key);
StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.groupingBy(t -> t.f0)) // yields a Map<String, List<Tuple2<String, Boolean>>>
.values() // yields a Collection<List<Tuple2<String, Boolean>>>
.stream()
.forEach(l -> {
System.out.println("l.size: " +l.size());
// l is the list of tuples for some common f0
while (l.size() > 1) {
Tuple2<String, Boolean> t0 = l.get(0);
System.out.println("t0: " +t0);
l = l.subList(1, l.size());
l.stream()
.filter(t -> t.f1 != t0.f1)
.forEach(t -> System.out.println("t: "+ t));
}
});
}
}
结果是:
key: (868789022645948,true)
key: (868789022645948,false)
l.size: 2
l.size: 2
t0: (868789022645948,true)
t0: (868789022645948,false)
此测试的结论:就像从未满足条件.filter(t -> t.f1 != t0.f1)
如果我将.filter(t -> t.f1 != t0.f1)
的{{1}}更改为.filter(t -> t.f1 != true)
(或为false),则过滤器有效
我还使用以下内容:
final Boolean[] aux = new Boolean[1];
<...>
Tuple2<String, Boolean> t0 = l.get(0);
aux[0] = t0.f1;
<...>
.filter(t -> !t.f1.equals(aux[0]))
但是即使那样,我也没有任何输出(我只有在使用t.f1.equals(aux[0])
时才得到它
答案 0 :(得分:0)
Iterable
允许您根据需要在其元素上获取尽可能多的Iterator
,但每个元素都对 all 元素进行一次迭代。因此,您使用forEachRemaining()
的想法将不会如您所愿。因为您正在生成一个新的Iterator
来调用该方法,所以它将从头开始而不是从另一个迭代器最近提供的元素之后开始。
您可以做的是使用Stream
的{{1}}创建一个Iterable
,并使用分组依据Spliterator
将可迭代的元组分组他们的第一个价值。然后,您可以根据需要处理元组列表。
例如,尽管我不确定这是否是您真正想要的东西,但这可以实现问题中描述的逻辑:
Collector
请注意,它可以多次收集相同的元组,如下所示。如果您想要不同的东西,例如仅收集表示给定StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.groupingBy(t -> t.f0)) // yields a Map<String, List<Tuple2<String, Boolean>>>
.values() // yields a Collection<List<Tuple2<String, Boolean>>>
.stream()
.forEach(l -> {
// l is the list of tuples for some common f0
while (l.size() > 1) {
Tuple2<String, Boolean> t0 = l.get(0);
l = l.subList(1, l.size());
l.stream()
.filter(t -> t.f1 != t0.f1)
.forEach(t -> collect(t));
}
});
的{{1}}值翻转的元组,则每个一次,那么您将希望在外部{{1}中使用不同的lambda实现}操作。