Cleaning a list of data in Java8
If modifying the list in-place is allowed, you could use
public <T> List<T> cleanData(List<T> data, List<Function<T, T>> cleanOps) {
cleanOps.stream().reduce(Function::andThen).ifPresent(f -> data.replaceAll(f::apply));
return data;
}
andThen
combines two Function
instances and if at least one function was present, i.e. the cleanOps
list is not empty, the resulting combined function will be applied to all list elements and the elements replaced by the result, using replaceAll
.
Unfortunately, replaceAll
requires a UnaryOperator<T>
rather than a Function<T,T>
, despite being functionally equivalent, so we have to use the adapter f::apply
.
Since these function types are equivalent, we could change the list to List<UnaryOperator<T>>
, but then, we have to face the fact that there is no specialized andThen
implementation for UnaryOperator
, so we would need:
public <T> List<T> cleanData(List<T> data, List<UnaryOperator<T>> cleanOps) {
cleanOps.stream()
.reduce((f1,f2) -> t -> f2.apply(f1.apply(t)))
.ifPresent(data::replaceAll);
return data;
}
The caller’s source changes to
List<UnaryOperator<String>> cleanOps = new ArrayList<>();
cleanOps.add(String::toLowerCase);
cleanOps.add(str -> str.replaceAll(" ", ""));
List<String> data = new ArrayList<>();
data.add("John Doe");
data.add("Jane Doe");
System.out.println(cleanData(data, cleanOps));
then.
As a side note, there is no need for a construct like
System.out.println(Arrays.toString(cleanData(data, cleanOps).toArray()));
as the toString()
method of a List
produces exactly the same output. Since the println(Object)
method calls toString()
implicitly, you can just use
System.out.println(cleanData(data, cleanOps));
It looks like you need to use List.replaceAll()
, which replaces each element of this list with the result of applying the given operator to that element.
public <T> List<T> cleanString(List<T> data, List<Function<T, T>> cleanOps) {
data.replaceAll(str -> {
T cleanData = str;
for (Function<T,T> function : cleanOps) {
cleanData = function.apply(cleanData);
}
return cleanData;
});
return data;
}
I'd rename the method, though, since it's generic, so it doesn't necessarily process a List
of String
s.