Как объединить две картыи рассчитать разницу между значениями в наносекундах - PullRequest
0 голосов
/ 28 сентября 2019

все.Я столкнулся с проблемой, когда пытался объединить две карты Map<String, LocalDateTime>.IDE показывает мне ошибку компиляции:

Нестатический метод не может быть вызван из статического контекста

Дело в том, что мне нужно объединить их в новый с другим параметромв качестве значения в этом случае мне нужно вычислить разницу между LocalDateTime первой карты и LocalDateTime секунды, поэтому результат должен быть Map<String, Long>

Map<String, Long> result = Stream.concat(logStartTimeMap.entrySet().stream(), logEndTimeMap.entrySet().stream())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (value1, value2) -> new Long(ChronoUnit.NANOS.between(value1,value2))));

Я получаю ошибку в строке Map.Entry :: getKey, Map.Entry :: getValue.

И еще один в строке ChronoUnit.NANOS.between(value1,value2), поскольку IDE считает, что value1 и value2 имеют тип Object вместо Temporal.И это довольно странно, потому что раньше я получал эту ошибку, когда выбирал неверный тип параметра в результате Map.Но здесь все в порядке, ChronoUnit.NANOS.between(value1,value2) возвращает Long, а результат Map имеет Long в качестве параметра.

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

То, как вы используете Collectors.toMap, означает, что вы пытаетесь вернуть Map<String, LocalDateTime>.Это потому, что Map.Entry::getKey возвращает String, а Map.Entry::getValue возвращает LocalDateTime.Затем в функции слияния вы пытаетесь вернуть Long, который не соответствует общей сигнатуре.

Вместо этого вы можете сделать что-то вроде следующего:

Map<String, LocalDateTime> map1 = ...;
Map<String, LocalDateTime> map2 = ...;

Map<String, Duration> result = map1.entrySet().stream().collect(Collectors.toMap(
        Map.Entry::getKey,
        entry -> Duration.between(entry.getValue(), map2.get(entry.getKey()))
));

Выше вычисляетсяDuration, который дает вам больше гибкости, чем просто наносекунды, но вы, очевидно, можете изменить это в соответствии со своими потребностями:

Map<String, LocalDateTime> map1 = ...;
Map<String, LocalDateTime> map2 = ...;

Map<String, Long> result = map1.entrySet().stream().collect(Collectors.toMap(
        Map.Entry::getKey,
        entry -> entry.getValue().until(map2.get(entry.getKey()), ChronoUnit.NANOS)
));

Обратите внимание, что в обоих примерах выше предполагается, что набор ключей map1является подмножеством набора ключей map2 комментарии вы говорите:

У меня одинаковые ключи на обеих картах.Ключ математики должен быть на второй карте.Таким образом, исключается ситуация, когда нет соответствующего ключа

Это означает, что предположение является действительным.Однако, если это предположение становится неверным, все, что вам нужно сделать, это добавить операцию фильтрации, при которой вы исключаете любую запись из map1, ключ которой отсутствует в map2.Равиндра показывает пример этого в своем ответе .

0 голосов
/ 28 сентября 2019

Я не вижу способа сделать это, объединив две карты в один поток.

Функция mergeFunction (третий параметр Collectors.toMap) должна быть BinaryOperator<U>.Это означает что-то вроде (U, U) -> U. Но в вашем коде он принимает два параметра типа LocalDateTime и возвращает Long.

Вы можете сделать это с такими потоками:

Map<String, Long> result = logStartTimeMap.entrySet().stream()
      .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), ChronoUnit.NANOS.between(e.getValue(), logEndTimeMap.get(e.getKey()))))
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...