Исходить надо из постановки задачи, а не из кода на скрине. По какому условию нужно выбирать между билдерами, и сколько раз и в каком порядке добавлять в них символы? От этого вообще весь алгоритм может зависеть.
И потом, что значит "лучше", кому "лучше"? Выбери одну парадигму и в ней реализуй. Если цикл, то цикл, если стрим, то стрим. А у тебя их уже зоопарк в такой короткой программе.
Как общий принцип, стримы Java заточены под редукцию в один аккумулятор (метод Stream.collect). Можно и в два билдера собирать в параллель, но потребуется больше кода, т.к. это нестандартный сценарий.
Или можно делать по-колхозному, объявить вне стрима эти два билдера и написать такое вот уродство:
StringBuilder stbL = new StringBuilder(),
stbR = new StringBuilder();
hm.entrySet().stream()
.filter(x -> x.getValue() % 2 == 1)
.forEach(x -> (условие для x ? stbL : stbR).append(x.getKey()));
В проектах ПТУшников очень любят такой подход, т.к. слово stream выучили, а программировать в понятиях теории категорий и лямбда-исчисления не научились.
А вот это зачем нужно?
if (hm.containsKey(ch)) {
int oldValue = hm.get(ch);
hm.put(ch, oldValue + 1);
} else {
hm.put(ch, 1);
}
Нельзя было проще написать?
hm.put(ch, hm.getOrDefault(ch, 0) + 1);
Это вообще зачем размазывать на три строки?
.filter(x -> {
return x.getValue() % 2 == 1;
})
Есть короткий и более читабельный синтаксис для таких штук:
.filter(x -> x.getValue() % 2 == 1)
Об этом даже среда предупреждает и предлагает заменить. Не ленись читать предупреждения среды и устранять их.
Такое впечатление, что готовишься к работе в бодишопе, где платят за строчки кода и прочую имитацию бурной деятельности.
Мне для прохождения по строке лучше использовать новый Stream или дописать код к уже существующему? Или тут лучше использовать цикл?