Искра - Количество слов Альтернативный подход - PullRequest
1 голос
/ 05 февраля 2020

У меня есть 1 миллион строк. Есть ли альтернативный способ реализовать подсчет слов в искре, кроме традиционного подхода отображения каждого слова в 1 и затем уменьшения его по ключу?

Традиционный подход:

JavaPairRDD<String, Integer> counts = textFile.flatMap(s -> 
                         Arrays.asList(SPACE.split(s)).iterator())
        .mapToPair(s -> new Tuple2<>(s, 1))
        .reduceByKey((a, b) -> a + b);

Есть ли новый подход?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

импорт требуемых пакетов, таких как "org. apache .spark. sql .functions. *"

Scala:

val strDF = spark.read.text("test.txt")
strDF.select(explode(split(col("line")," ")).as("word")).groupBy(col("word")).count.show

Java:

String filePath = "/test.txt";
Dataset<Row> lines = sparkSession.read().text(filePath).toDF("line");
lines.select(explode(split(col("line")," ")).as("word")).groupBy("word").count().show();

0 голосов
/ 05 февраля 2020

Конечно, есть много способов сделать это. Вот 2:

Один: плоская карта и создание фрейма данных:

JavaRDD<Row> rowRdd = spark.read()
        .textFile("loremipsum.txt")
        .javaRDD()
        .flatMap(s -> Arrays.asList(s.split(" ")).iterator())
        .map(s -> RowFactory.create(s));
spark.createDataFrame(rowRdd,
                      new StructType()
                     .add(DataTypes.createStructField("word", DataTypes.StringType, true)))
      .groupBy("word")
      .count()
      .show();

Печать что-то вроде:

+------------+-----+
|        word|count|
+------------+-----+
|         Sit|   17|
|        Elit|    6|
|   vehicula.|    2|
|       eros.|    2|
|        nam.|    3|
|   porttitor|   18|
|consectetur.|    6|
...

Бонус: используйте SQL группировать (если это считается еще одной альтернативой)

Два: группировать по словам и считать элементы в итерациях:

Map<String, Long> counts = spark.read().textFile("loremipsum.txt")
        .javaRDD()
        .flatMap(s -> Arrays.asList(s.split(" ")).iterator())
        .groupBy(i -> i)
        .aggregateByKey(0L, (id, it) -> countIterable(it), (a, b) -> a + b)

        .collect() //collection of Tuple2: you can stop here
        .stream()
        .collect(Collectors.toMap(t -> t._1, t -> t._2));

В результате получается что-то вроде:

{=50, Malesuada=4, justo.=3, potenti=2, vel.=11, purus=30, curabitur.=2...}

с countIterable определяется как:

private static <T> long countIterable(Iterable<T> it) {
    long res = 0;
    for (T t : it)
        res += 1;
    return res;
}

, который также может быть реализован как

return StreamSupport.stream(it.spliterator(), false).count();
...