Преобразование массива в карту 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.
Изменить: Однако, это не похоже, что это обязательно будет работать, потому что, судя по подписи коллекционера это:
- Ожидает поток
Tuple<K,V>
- Собирает все элементы этого потока в
ArrayList<Tuple2<K,V>>
- После того, как все элементы были собраны, он "заканчивает", добавляя все содержимое этого
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, и я не могу проверить, скомпилирован ли фрагмент кода выше, но похоже, что он делает то, что вы хотите.