Generic way to update pojos via getters and setters
Use something like
private static final List<BiConsumer<Entity,Entity>> ACCESSORS =
Collections.unmodifiableList(Array.asList(
(src,dst) -> dst.setAreaCode(src.getAreaCode()),
(src,dst) -> dst.setOtherProperty(src.getOtherProperty())
/* etc */
));
Then, you can loop over the list and apply each operation to two entities, like
static final void copyAll(Entity src, Entity dst) {
ACCESSORS.forEach(op -> op.accept(src, dst));
}
The key point is that the actual property value type is handled within each BiConsumer
but is not part of the generic signature anymore and therefore doesn’t need to be declared for ACCESSORS
. It’s even more efficient, as it can handle primitive data types without boxing overhead.
The Map
wasn’t an appropriate data structure for this task anyway, as for these functions, no meaningful lookup could be performed, so this is a data structure is only intended to be iterated over.
You can integrate the “copy only when non-null” logic with a generic helper method:
private static final List<BiConsumer<Entity,Entity>> ACCESSORS =
Collections.unmodifiableList(Arrays.asList(
copyWhenNonNull(Entity::getAreaCode, Entity::setAreaCode),
copyWhenNonNull(Entity::getOtherProperty, Entity::setOtherProperty)
/* etc */
));
private static <E,V> BiConsumer<E,E> copyWhenNonNull(
Function<? super E, ? extends V> getter, BiConsumer<? super E, ? super V> setter) {
return (src,dst) -> {
V value = getter.apply(src);
if(value != null) setter.accept(dst, value);
};
}
The copyAll
method doesn’t change. This even allows mixing unconditional copying of properties which can never be null
with conditional copying.