避免在JavaPairRDD Apache Spark中使用Group By

时间:2017-10-24 14:06:13

标签: java apache-spark

我已经使用JavaRDD在Spark中重写了这段代码。我读到groupByKey操作费用很高。

我们可以通过避开groupByKey来重写它。

按键分组后,我正在尝试更新密钥的值(如果适用)。

可以帮助一些人

    /* Curiously Recurring Template Pattern  */
template <typename T, template<typename> class crtpType>
struct crtp
{
    T& underlying() { return static_cast<T&>(*this); }
    T const& underlying() const { return static_cast<T const&>(*this); }
};

/* Inheriting class can be divided by a scalar */
template<typename T>
struct Divable : crtp<T, Divable>
{
    T operator/(double const& scalar) const { return T(this->underlying().get() / scalar); }
};

/* Inheriting class can be divided by itself */
template<typename T>
struct Ratioable : crtp<T, Ratioable>
{
    double operator/(T const& other) const { return this->underlying().get() / other.get(); }
};

struct DoubleWrapper : 
    public Divable<DoubleWrapper>, 
    public Ratioable<DoubleWrapper>
{
    explicit DoubleWrapper(double val) : val_(val) {}

    double get() const { return val_; }

private:
    double val_;
};

JavaRDD

    List<Items> items = getItems();
    Map<String, List<ItemId>> itemsByName = items.stream()
            .collect(Collectors.groupingBy(ItemId::getName, Collectors.toList()));

    List<ItemId> newItems = itemsByName.entrySet().stream()
            .collect(Collectors.toMap(e -> e.getKey(), e -> {
            //update values if applicable
                List<ItemId> rps = e.getValue().stream().filter(s -> s.isApplicable()).collect(Collectors.toList());
                return rps.isEmpty() ? e.getValue() : rps;
            }))
            .values().stream()
            .flatMap(x -> x.stream()).collect(Collectors.toList());

我正在尝试做类似的事情,但在java中 How to update column based on a condition (a value in a group)?

1 个答案:

答案 0 :(得分:1)

应避免使用GroupByKey。尝试使用reduceByKey,它会在使用相同的密钥对数据进行混洗之前在每个分区上应用您的函数。

洗牌的数据越少越好。

这是一个很好的例子https://databricks.gitbooks.io/databricks-spark-knowledge-base/content/best_practices/prefer_reducebykey_over_groupbykey.html