Ваша основная проблема заключается в том, что сопоставление каждого метода MyBuilder
каждому типу MyDto
является произвольным, т. Е. У Java нет способа автоматически узнать, какой метод вызывать для каждого типа: вы должны указать Java, какой ,
Итак, если каждый метод компоновщика сопоставлен с различным значением dto.getType()
, самый простой способ сообщить Java, это переместить switch
в общий метод внутри MyBuilder
, который позволяет вам сообщить соответствующее поле, как это:
public MyBuilder fieldFromDto(MyDto dto) {
switch (dto.getType()) {
case FIELD1: return field1(dto.getValue);
case FIELD2: return field2(dto.getValue);
//...
Итак, вы могли бы сделать именно это:
MyBuilder builder = new MyBuilder();
col.stream().forEach(builder::fieldFromDto);
Some result = builder.build();
Другая возможность состояла бы в том, чтобы превратить этот переключатель в лямбда-карту (Type
и Value
- это типы полей MyDto
):
class MyBuilder {
public final Map<Type, Function<Value, MyBuilder>> mappings = new Map<>();
public MyBuilder() {
mappings.put(FIELD1, this::field1);
mappings.put(FIELD2, this::field2);
//...
}
А затем используйте эти лямбды в forEach
:
MyBuilder builder = new MyBuilder();
col.stream().forEach(dto -> builder.mappings.get(dto.getType()).apply(dto.getValue()));
Some result = builder.build();
Кроме этого, вы можете использовать рефлексию, как некоторые другие предложенные ответы, но тогда вам нужно убедиться, что FIELD1
, FIELD2
и т. Д. Являются действительными MyBuilder
именами методов, теряя некоторую гибкость.
В конце концов, я бы не советовал делать что-либо из вышеперечисленного. Потоки хороши, но иногда они не дают никаких преимуществ по сравнению с обычным циклом for
и могут сделать ваш код более уродливым и трудным в обслуживании.