获取DStream的第一个元素(带函数)

时间:2015-02-24 14:06:24

标签: scala apache-spark spark-streaming

我寻找一种方法来检索创建为:

的DStream的第一个元素
val dstream = ssc.textFileStream(args(1)).map(x => x.split(",").map(_.toDouble)) 

不幸的是,dstream上没有采取功能(如在RDD上)//dstream.take(2) !!!

有人可以知道怎么做吗?感谢

4 个答案:

答案 0 :(得分:1)

您可以在DStream对象中使用transform方法,然后获取输入RDD的n个元素并将其保存到列表中,然后过滤原始RDD以包含在此列表中。这将返回一个包含n个元素的新DStream。

val n = 10
val partOfResult = dstream.transform(rdd => {
  val list = rdd.take(n)
  rdd.filter(list.contains)
})
partOfResult.print

答案 1 :(得分:1)

之前建议的解决方案没有为我编译,因为 take()方法返回一个不可序列化的数组,因此Spark流将失败并带有 java.io.NotSerializableException

以前代码的一个简单变体对我有用:

val n = 10
val partOfResult = dstream.transform(rdd => {
  rdd.filter(rdd.take(n).toList.contains)
})
partOfResult.print

答案 2 :(得分:0)

共享对我有用的基于Java的解决方案。想法是使用自定义函数,该函数可以从已排序的RDD发送第一行。

            someData.transform(
                     rdd ->
                    {

                        JavaRDD<CryptoDto> result = 
                                rdd.keyBy(Recommendations.volumeAsKey)
                        .sortByKey(new CryptoComparator()).values().zipWithIndex()
                        .map(row ->{
                            CryptoDto purchaseCrypto = new CryptoDto();
                            purchaseCrypto.setBuyIndicator(row._2 + 1L);
                            purchaseCrypto.setName(row._1.getName());
                            purchaseCrypto.setVolume(row._1.getVolume());
                            purchaseCrypto.setProfit(row._1.getProfit());
                            purchaseCrypto.setClose(row._1.getClose());
                            return purchaseCrypto;  
                        }
                        ).filter(Recommendations.selectTopinSortedRdd);
                        return result;
                    }).print();

自定义函数selectTopinSortedRdd如下所示:

                public static Function<CryptoDto, Boolean> selectTopInSortedRdd = new Function<CryptoDto, Boolean>() {
                    private static final long serialVersionUID = 1L;
                    @Override
                    public Boolean call(CryptoDto value) throws Exception {
                        if (value.getBuyIndicator() == 1L) {
                            System.out.println("Value of buyIndicator :" + value.getBuyIndicator());
                            return true;
                        }
                        else {
                        return false;
                    }
                }
                };

它基本上比较所有传入的元素,并且仅对已排序的RDD中的第一条记录返回true

答案 3 :(得分:0)

这似乎一直是DStreams和常规RDD的问题。

如果您不希望(或不能)使用.take()(尤其是在DStreams中),则可以在此处跳出框框,而只需使用reduce即可。这对于DStreams和RDD都是有效的函数。

考虑一下。如果您这样使用reduce(Python示例):

.reduce( lambda x, y : x)

然后发生的是:每传入2个元素,始终仅返回第一个。因此,如果RDD或DStream中有一百万个元素,它将最终缩小到一个元素,这是RDD或DStream中的第一个元素。

简单干净。

但是请记住,.reduce()没有考虑顺序。但是,您可以使用自定义函数轻松解决此问题。

示例:假设您的数据看起来像x =(1,[1,2,3])和y =(2,[1,2])。元组x,其中第二个元素是一个列表。例如,如果按最长列表进行排序,则您的代码可能如下所示(根据需要进行调整):

    def your_reduce(x,y):
      
      if len(x[1]) > len(y[1]):
        return x
      else:
        return y 

yourNewRDD = yourOldRDD.reduce(your_reduce)

因此,您将得到'(1,[1,2,3])',因为该列表较长。你去了!

在过去,这使我有些头疼,直到我最终尝试为止。希望这会有所帮助。