在Iterable上查找元素

时间:2019-04-29 15:45:13

标签: java apache-flink

我有以下课程:

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])时才得到它

1 个答案:

答案 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实现}操作。