Reputation: 739
Is there a simple way to split a list into sublists by grouping only repeated elements that are adjacent to each other?
Simple example with the folowing list of strings:
Input: [RED,RED,BLUE,BLUE,BLUE,GREEN,BLUE,BLUE,RED,RED]
Output: [[RED,RED],[BLUE,BLUE,BLUE],[GREEN],[BLUE,BLUE],[RED,RED]]
If I use groupingBy from java streams all elements which are equal will end up in the same sublist, which I want to avoid. Any ideas?
Upvotes: 2
Views: 257
Reputation: 117627
You can create a custom collector:
List<String> input = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
List<List<String>> output = input.stream()
.collect(Collector.of(ArrayList::new, (accumulator, item) ->
{
if(accumulator.isEmpty())
{
List<String> list = new ArrayList<>();
list.add(item);
accumulator.add(list);
}
else
{
List<String> last = accumulator.get(accumulator.size() - 1);
if(last.isEmpty() || last.get(0).equals(item)) last.add(item);
else
{
List<String> list = new ArrayList<>();
list.add(item);
accumulator.add(list);
}
}
}, (left, right) -> {left.addAll(right); return left;}));
Upvotes: 3
Reputation: 1760
I'm sure there's a better way to do this with streams, but for a quick and dirty:
List<String> values = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
List<List<String>> output = new ArrayList<List<String>>();
String previous = null;
List<String> subList = new ArrayList<String>();
for (String value : values) {
if (previous == null || value.equals(previous)) {
subList.add(value);
} else {
output.add(subList);
subList = new ArrayList<String>();
subList.add(value);
}
previous = value;
}
if (!subList.isEmpty()) {
output.add(subList);
}
System.out.println(output);
Upvotes: 2