Tengo una lista de objetos, cada objeto tiene una identificación. Quiero agrupar elementos por su id dado que son consecutivos. Como, si los objetos son:
(id1, id1, id1, id2, id2, id3, id3, id2, id2, id4)entonces los grupos deben ser:
(id1, id1, id1), (id2, id2), (id3, id3), (id2, id2), (id4)¿Se puede lograr esto con la API de flujos de Java?
Esto es muy posible usando la reducción mutable que da como resultado List<List<String>> . Para una mejor legibilidad, recomiendo dividir en métodos:
List<List<String>> newList = list.stream().collect( ArrayList::new, (lists, string) -> { if (lists.isEmpty()) { withNewList(lists, string); } else { withNewString(lists, string); } }, ArrayList::addAll ); // adds a new inner list with a single item (string) static void withNewList(ArrayList<List<String>> lists, String string) { List<String> newList1 = new ArrayList<>(); newList1.add(string); lists.add(newList1); } static void withNewString(ArrayList<List<String>> lists, String string) { // if the last inserted list has a same item List<String> lastList = lists.get(lists.size() - 1); if (lastList.contains(string)) { // append it to the last inner list lastList.add(string); } else { // or else create a new list with a single item (string) withNewList(lists, string); } } Teniendo en cuenta la siguiente list de entrada:
List<String> list = List.of( "id1", "id1", "id1", "id2", "id2", "id3", "id3", "id2", "id2", "id4");... cuando imprime el resultado, la salida se ve así:
[[id1, id1, id1], [id2, id2], [id3, id3], [id2, id2], [id4]]
Para facilitar la navegación hasta el último elemento (anterior), usaría una LinkedList de LinkedLists:
public static void main(String[] args) { ... Stream.of(id1, id1, id1, id2, id2, id3, id3, id2, id2, id4) .sequential() // order is essential .collect(LinkedList::new, (listOfLists, object) -> { if (listOfLists.isEmpty() || listOfLists.getLast().getLast() != object) { listOfLists.add(new LinkedList<>(List.of(object))); } else { listOfLists.getLast().add(object); } }, List::addAll); ... }