#java #collections #java-stream
Вопрос:
У меня есть карта со смешанными случаями, например
{a=[v1, V1], A={v2, V2, v3}
Я бы хотел, чтобы все было в нижнем регистре,
{a=[v1, v2, v3]}
Я сделал это многословно на Java, задаваясь вопросом, есть ли какой-нибудь простой/лучший способ. Спасибо
Map<String, Set<String>> result = new HashMap<>();
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
String key = entry.getKey().toLowerCase();
Set<String> currSet = entry.getValue().stream().map(v -> v.toLowerCase()).collect(Collectors.toSet());
Set<String> existSet = result.get(key);
if (existSet == null) {
result.put(key, currSet);
} else {
existSet.addAll(currSet);
}
}
Комментарии:
1. Я уверен, что вы можете сделать это с помощью одного потока без дополнительных шагов.
Ответ №1:
Вы можете использовать putIfAbsent()
или computeIfAbsent()
предотвратить ненужное создание экземпляра набора на карте , чтобы создать новый набор, если значения еще нет, а затем просто позвонить addAll()
Map<String, Set<String>> result = new HashMap<>();
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
String key = entry.getKey().toLowerCase();
Set<String> currSet = entry.getValue().stream().map(v -> v.toLowerCase()).collect(Collectors.toSet());
result.computeIfAbsent(key, k -> new HashSet<>()).addAll(currSet);
}
putIfAbsent()
аналогично, но опять же, он всегда будет создавать новый хэш-набор вместо создания только одного экземпляра, если значение на самом деле отсутствует:
result.putIfAbsent(key, new HashSet<>()).addAll(currSet);
Ответ №2:
В случае, если вы являетесь поклонником java-потока:
@Test
void mapToMap() {
// Map.of: Java 9 or higher
Map<String, Set<String>> before = Map.of("A", Set.of("A", "a"), "a", Set.of("b", "B", "c"));
// Collectors.toMap: Java 8 or higher
Map<String, Set<String>> after = before.entrySet().stream().collect(
Collectors.toMap(
e -> e.getKey().toLowerCase(),
e -> e.getValue().stream().map(String::toLowerCase).collect(Collectors.toSet()),
(existing, replacement) -> {
existing.addAll(replacement);
return existing;
}
)
);
assertThat(after.size()).isEqualTo(1);
assertThat(after.get("a")).containsExactly("a", "b", "c");
}
Ответ №3:
Вы можете использовать Map.computeIfAbsent()
вот так.
public static void main(String[] args) throws IOException {
Map<String, Set<String>> input = Map.of(
"a", Set.of("v1", "V1"),
"A", Set.of("v2", "V2", "v3"));
Map<String, Set<String>> output = new LinkedHashMap<>();
for (Entry<String, Set<String>> e : input.entrySet())
output.computeIfAbsent(e.getKey().toLowerCase(), k -> new HashSet<>())
.addAll(e.getValue().stream().map(String::toLowerCase).toList());
System.out.println(output);
}
выход:
{a=[v1, v2, v3]}