Преобразование массива в карту Javaslang с количеством для каждого типа

В настоящее время я смотрю на библиотеку Javaslang и пытаюсь преобразовать часть своего кода в Javaslang.

В настоящее время у меня есть этот кусок кода, который все чисто Java

Cell[][] maze; //from input
Map<Cell, Long> cellCounts = Stream.of(maze)
            .flatMap(Stream::of)
            .collect(groupingBy(c -> c, counting()));

Я пытался преобразовать это в Javaslang, так как мне интересна библиотека, и я просто хотел поиграть с ней.

Я пытаюсь сделать аналогичную вещь, но преобразовать в карту Javaslang вместо java.util.Map.

Я пробовал это до сих пор, но затем я застреваю, так как я не вижу способа преобразовать это.

Array.of(maze)
     .flatMap(Array::of)

Итак, у меня есть список объектов Cell, но я пытаюсь выяснить, как преобразовать его в javaslang.collection.Map.

*РЕДАКТИРОВАТЬ *

Я посмотрел на получение моего оригинального java.util.Map к javaslang.collections.Hashmap этим

HashMap<Cell, Long> cellsCount = HashMap.ofEntries(cellCounts
                                                        .entrySet()
                                                        .toArray(new Map.Entry[0]));

Это по-прежнему не соответствует Javaslang, но я буду продолжать искать.

3 ответа

Решение

Отказ от ответственности: я автор Javaslang.

Этот самый простой способ добиться этого с помощью Javaslang заключается в следующем:

    Map<Cell, Integer> cellCounts = Array.of(maze)
            .flatMap(Array::of)
            .groupBy(c -> c)
            .mapValues(Array::length);

Вот Array а также Map импортируются из javaslang.collection,

Обратите внимание, что вы можете заменить Array с любым другим Seq или же Set реализация.

Как правило, группировка по имеет другой метод, который принимает реализацию Map, в которую вы пытаетесь преобразовать, но это должен быть тип, который на самом деле расширяет java.util.Map:

Collectors.groupingBy(classifier, mapFactory, downstream)

Из того, что я вижу javaslang.collection.Map это интерфейс, а не фактическая реализация.

Так как нет реализации javaslang Map, которая бы расширяла java.util.Mapвсе, что вы можете сделать, это создать собственный коллектор.

Или когда-то уже собрали java.util.Map - положить их в какой-то случай javaslang.collection.Map,

Хотя ответ на то, что предоставил Евгений, в общем и целом правдив: кто-то должен сделать коллектор на заказ.

Однако это не обязательно должен быть вы: ребята из Javaslang уже позаботились об этом за вас, предоставив необходимые методы, доступные в конкретных реализациях карт Javaslang, которые будут работать в самых простых случаях. Например, на Javaslang HashMap:

javaslang.collection.HashMap:: коллектор ()

открытый статический коллектор , ArrayList >, HashMap > collector ()

Возвращает Collector, который можно использовать вместе с Stream.collect(java.util.stream.Collector) для получения HashMap.

Параметры типа:

K - тип ключа

V - тип значения

Возвращает:

HashMap Collector.

Изменить: Однако, это не похоже, что это обязательно будет работать, потому что, судя по подписи коллекционера это:

  1. Ожидает поток Tuple<K,V>
  2. Собирает все элементы этого потока в ArrayList<Tuple2<K,V>>
  3. После того, как все элементы были собраны, он "заканчивает", добавляя все содержимое этого ArrayList в HashMap,

Это, очевидно, не будет работать, так как у вас есть Stream<Cell> и вы хотите их посчитать. Однако эта подпись фактически дает нам несколько вещей: она указывает на то, что встроенный сборщик Javaslang не собирается непосредственно в карту Javaslang (по крайней мере, в HashMap). Зная это, мы можем найти метод для преобразования Java Map в карту Javaslang, и мы найдем:

javaslang.collection.HashMap:: ofAll (java.util.Map)

Возвращает HashMap из источника java.util.Map.

Мы можем добавить этот метод поверх того, что у вас есть:

Stream<Cell> cells // <- you have this

cells.collect(
  collectingAndThen(
    groupingBy(Function.identity(), counting()),
    HashMap::ofAll
  )
);

Все методы без классификаторов вы можете найти в java.util.stream.Collectors,

Этот фрагмент будет собираться в обычную Java Map и в качестве последнего шага вызовет финишер Collector, который поместит все значения из java Map в карту Javaslang.

Примечание: у меня не установлен Javaslang, и я не могу проверить, скомпилирован ли фрагмент кода выше, но похоже, что он делает то, что вы хотите.

Другие вопросы по тегам