This is my problem: I have a list of event names in chronological order, example:
ArrayList<String> eventsOrder = new ArrayList<>(Arrays.asList("event1", "event2", "event3", "event4", "event5"));
I have HashMap of data about events, where key is events name, example:
HashMap<String, String> eventsData = new HashMap<>();
eventsData.put("event2", "data2");
eventsData.put("event1", "data1");
eventsData.put("event3", "data3");
I also have a method that merges Data from 2 events into 1:
public String merge(String previousEventsData, String nextEventsData);
I need to merge all of events' data into one object in chronological order. So in this case it would be something like this:
merge(merge("data1", "data2"),"data3");
This how I solve it now:
Firstly, this HashMap may or may not contain data about all of the events so i filter names of the ones that are available:
ArrayList<String> eventsToProcess = eventsOrder.stream()
.filter(eventName -> eventsData.containsKey(eventName))
.collect(Collectors.toCollection(ArrayList::new));
Then I use this ugly algorithm to merge events' data in chronological order:
String finalData = "";
int eventsCount = namesToProcess.size();
finalData = eventsData.get(namesToProcess.get(0));
if(eventsCount > 1) {
for (int i = 1; i < eventsCount; i++){
finalData = merge(finalData, eventsData.get(namesToProcess.get(i)));
}
}
Not very elegant and readable, right?
Question: How would I do same processing with Java streams or a recursive function?
Something like this should be equivalent, using Stream.reduce
:
eventsOrder.stream() // "event1", "event2", "event3", "event4", "event5"
.map(eventsData::get) // "data1", "data2", "data3", null, null
.filter(Objects::nonNull) // "data1", "data2", "data3"
.reduce(YourClass::merge) // merge(merge("data1", "data2"), "data3")
.get() // gets the result from the Optional
The Optional.get
method throws NoSuchElementException
if there are no events with data; your original code's namesToProcess.get(0)
will throw IndexOutOfBoundsException
in that case. That should be the only difference in behaviour, assuming your eventsData
map doesn't have any null
values.