В настоящее время я читаю файл через Java API и добавляю элементы на карту с помощью метода foreach, который заставляет меня использовать mutablemap. Есть ли способ собирать предметы без mutablemap? Я знаю, что есть метод сбора, но я не смог заставить его работать.

Текущий способ:

    val result = mutableMapOf<Int, MutableMap<Int, Double>>()
    Files.lines(Paths.get(folderPath))
                    .map { line -> line.split(",") }
                    .map { items -> Triple(items[0].toInt(), items[1].toInt(), items[2].toDouble()) }
                    .forEach { (id, article, rating) ->
                        if (result.containsKey(id))
                            result[id]!!.put(article, rating)
                        else
                            result.put(id, mutableMapOf(Pair(article, rating)))
                    }

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

Моя цель - объединить тройные объекты на основе первого значения тройки. Таким образом, сценарий будет двумя тройными объектами (1, 2, 5.5) и (1,3, 5.5). Первое значение тройки - это идентификатор пользователя, второе - это идентификатор статьи, а третье - рейтинг статьи. после объединения на карте будет одна запись, содержащая первый ключ = идентификатор пользователя, первое значение тройки, а значением будет карта, содержащая статьи, которые оценил пользователь.

В настоящее время он работает так, как я хочу, чтобы он работал, но мне было любопытно, есть ли более функциональный способ решения этой проблемы.

3
Erik W 27 Май 2017 в 22:47

2 ответа

Лучший ответ

Вы могли бы сделать это:

val result: Map<Int, Map<Int, Double>> = Files.lines(Paths.get(folderPath))
        .map { it.split(",") }
        .collect(groupingBy({ it[0].toInt() },
                toMap<List<String>, Int, Double>({ it[1].toInt() }) { it[2].toDouble() }))

Компилятор не смог определить типы для toMap, поэтому я добавил подсказку типа.

Я укажу, что у Kotlin нет неизменной реализации Map. По умолчанию возвращается mapOf: java.util.LinkedhashMap, который является изменяемым. Просто интерфейс Map не предоставляет методы мутации (например, put, putAll). И вы можете свободно назначать MutableMap<Int, MutableMap<Int, Double>> на Map<Int, Map<Int, Double>>, что я и делаю здесь с аннотацией типа result, я заставляю статический тип быть неизменным { { Х9 } } .

2
Jorn Vernee 28 Май 2017 в 14:00

Мне не очень удобно с Kotlin, но, похоже, вам следует использовать простое: Collectors.collectingAndThen. Что-то вроде:

  System.out.println(Stream.of(1, 2, 3, 1)
             .collect(Collectors.collectingAndThen(
                  Collectors.groupingBy(Function.identity(), Collectors.counting()),
                       Collections::unmodifiableMap)));

Идея состоит в том, что вы собираете в изменяемую карту, а затем оборачиваете ее в ImmutableMap.

Если, кстати, у вас есть guava в пути к классам - у него есть сборщики сборок, которые собирают в ImmutableMap.

2
Eugene 28 Май 2017 в 09:12