Search code examples
javajava-8java-stream

Java Stream how to replace first item that meets criteria with the next item that meets criteria


I have a list of schedules that I need to update when one expires with the next one of the same name so I can maintain the order. Example:

List<Schedule> scheduleList = new ArrayList<>(List.of(
        new SchedA("a", 1),
        new SchedB("b", 2),
        new SchedC("c", 3),
        new SchedA("a", 4),
        new SchedB("b", 5),
        new SchedC("c", 6),
        new SchedA("a", 7),
        new SchedB("b", 8),
        new SchedC("c", 3),));

I think I could do this to remove the expired item:

scheduleList.stream().filter(p -> p.getScheduleId().equals("a")).findFirst().ifPresent(scheduleList::remove);

Is there something like this to replace it with the next item that has "a" as the scheduleId?


Solution

  • You should consider changing the data structure. A Map of Lists is better suited for this use case.

    Map<String, Schedule> map = new HashMap<>();
    map.put("a", List.of(new SchedA(1), new SchedA(4), new SchedA(7)));
    map.put("b", List.of(new SchedB(2), new SchedB(5), new SchedB(8)));
    map.put("c", List.of(new SchedC(3), new SchedC(6), new SchedC(9)));
    

    Now, if you want to remove, all you have to do is:

    map.get("a").remove(0);
    

    And getting the next item would be:

    map.get("a").get(0);
    

    On a side note, it also seems redundant to have the parameter a in new SchedA("a", 1) as you already have different SchedA subclasses anyways.


    If you really want to remove and replace, then streams won't be the ideal implementation:

    int first = -1;
    int second = -1;
    for (int i = 0; i < scheduleList.size(); i++) {
        Schedule schedule = scheduleList.get(0);
        if (schedule.getScheduleId().equals("a")) {
            if (first == -1) {
                first = i;
            } else if (second == -1) {
                second = i;
                break;    // found first two items
            }
        }
    }
    
    if (first != -1 && second != -1) {
        // found two items
        scheduleList.set(first, scheduleList.get(second));
    } else (first != -1) {
        // found one item only
        scheduleList.remove(first);
    } else {
        // no items found, do nothing
    }