I have a class with member variables:
class Filter{
private String key;
private String operator;
private Object value;
}
And List of Type Filter as below:
[
{
key: status,
operator:equal,
value: active
},
{
key: status,
operator:equal,
value: inactive
},
{
key: name,
operator:equal,
value: jhon
},
{
key: id,
operator:equal,
value: 123
}
]
I want to transform the above List into a new List as below where if the key is same key: status
then in new list need to have only one entry with value is in list type value: [active, inactive]
and operator will be IN
[
{
key: status,
operator:in,
value: [active, inactive]
},
{
key: name,
operator:equal,
value: jhon
},
{
key: id,
operator:equal,
value: 123
}
]
What is the best and efficient way to achieve this solution, preferably using Java 8 stream and lambdas? Wanted to avoid traditional for loop.
You can use Collectors.partitioningBy to split the List into two parts based on whether or not the Filter's key is "status". Demo
final Map<Boolean, List<Filter>> parts = list.stream()
.collect(Collectors.partitioningBy(f -> "status".equals(f.getKey())));
final Object[] statuses = parts.get(true).stream().map(Filter::getValue).toArray();
final List<Filter> result = parts.get(false);
if (statuses.length != 0) {
result.add(0, new Filter("status", "in", statuses));
}
For multiple keys, you can use Collectors.groupingBy. Demo
final Map<String, List<Filter>> map = list.stream().collect(Collectors.groupingBy(Filter::getKey, LinkedHashMap::new, Collectors.toList()));
final List<Filter> result = map.entrySet().stream()
.map(e -> e.getValue().size() > 1
? new Filter(e.getKey(), "in", e.getValue().stream().map(Filter::getValue).toArray())
: e.getValue().get(0))
.collect(Collectors.toList());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With