Преобразовать и ключ, и значение Map.Entry за один вызов stream().map()
У меня есть Stream<Map.Entry<?, ?>> и его нужно преобразовать в Stream<Map.Entry<Material, Long>>
(Material это enum)
Вот функции преобразования:
- ? -> Material:
entry -> Material.getMaterial(entry.getKey().toString())
- ? -> Long
entry -> entry.getValue() instanceof Number ?
((Number) entry.getValue()).longValue() : defaultTimeout
Material.getMaterial(String) представляет собой получение значения из HashMap<String, Material>, следовательно может возвращать null. Так как далее я использую EnumMap - мне нужно отфильтровать Entry, содержащие не валидные строки.
(и еще, мне не нужно выбрасывать IllegalArgumentException если строка не валидна, нужно просто пропустить содержащий ее Entry, поэтому метод Enum::valueOf мне не подходит)
Сейчас я использую:
ImmutableMap<Material, Long> outMap = configuration.getMapList("path")
.stream().flatMap(map -> map.entrySet().stream())
.filter(entry -> Material.getMaterial(entry.getKey().toString()) != null)
.collect(Maps.toImmutableEnumMap(entry -> Material.getMaterial(entry.getKey().toString()),
entry -> entry.getValue() instanceof Number ?
((Number) entry.getValue()).longValue() : defaultValue));
С одной стороны, все не очень плохо - строки не меняются => хеш не вычисляется повторно (он кэшируется классом String), но мне все еще не нравится лишний HashMap::get.
Могу ли я как то преобразовать и ключ, и значение Entry одним вызовом Stream::map, потом отфильтровать лишь по Entry.getKey() != null и собрать Maps.toImmutableEnumMap(entry -> entry.getKey(), entry -> entry.getValue())?
P.S. я использую Java 8, поэтому метод Map::entry() мне недоступен
UPDATE
Я стал использовать AbstractMap.SimpleImmutableEntry в своем коде (в методе map просто создаем новый SimpleImmutableEntry и в его конструктор уже передаем результаты методов преобразований). Словами получается не очень, это лучше увидеть:
ImmutableMap<Material, Long> outMap = configuration.getMapList("path")
.stream().flatMap(map -> map.entrySet().stream())
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(
Material.getMaterial(entry.getKey().toString()),
entry.getValue() instanceof Number ?
((Number) entry.getValue()).longValue() : defaultValue
)).filter(entry -> entry.getKey() != null)
.collect(Maps.toImmutableEnumMap(AbstractMap.SimpleImmutableEntry::getKey, AbstractMap.SimpleImmutableEntry::getValue));
Будет ли это оптимальным решением (именно пересоздавание Entry), если в исходном Stream может быть до 463 значений?