Java 8 stream: replace a single item in a stream collection

I am somewhat new to working on Java 8 and refactoring old code with (which seems to be a good use case) for the thread. The older code "works", but for my eyes it looks really inefficient.

The short version of my question is that I am trying to find one element from the list and replace it with an updated version of the same element (the key is the same, but the properties have different values ​​each time the code is called).

try { List<Object> items = lookup(itemCache.getKey()); for (int i = 0; i < items.size(); i++) { Object originalObject = items.get(i); if (originalObject.getPropValue() == newObject.getPropValue()) { List<Object> newItems = new ArrayList<>(items); newItems.set(i, newObject); putIntoCache(newObject.getKey(), newItems); break; } } } catch (Exception ex) { /*exception handling*/ } 

Based on what I've read about threads so far, it seems that I need to use .map() or .filter() to highlight the element that I want to identify, but it also looks like the operations that occur after filter or map in the stream operator will work either not in the full list or in the list where .map() affects each element.

It seems simple, but I'm struggling to circle my head. Since the initial search is a List , I thought a thread could replace all of this. ArrayList<>() appears in the source code, but the order of the elements is not important, as long as I can replace this element with its key.

If you decide to help, thanks.

+6
source share
3 answers

You can simply do:

 List<Object> newItems = items.stream() .map(o -> { if(o.getPropValue() == newObject.getPropValue()) { return newObject; } else { return o; } }).collect(toList()); putIntoCache(newObject.getKey(), newItems); 
+13
source

The function you want to apply is "replace the first element corresponding to the value of prop". The first part (and the break statement) are nontrivial (since you depend on all the records processed previously). In other words, this means that your function depends on some additional state, so the domain can be expressed as boolean * String , where a boolean value indicates whether a replacement has been made. You can see how it starts to get ugly.

If you agree to replace all relevant values, Jean Logeart's answer looks ok.

+2
source

Streams are actually not particularly good for this piece of code, because it has an early break and at the same time works with both indexes and elements.

You can create an equivalent statement as follows:

 List<Object> items = lookup(itemCache.getKey()); IntStream.range(0, items.size()) .filter(i -> items.get(i).getPropValue() == newItem.getPropValue()) .findFirst() .ifPresent(i -> { List<Object> newItems = new ArrayList<>(items); newItems.set(i, newObject); putIntoCache(newObject.getKey(), newItems); }); 

Is it really better? In my opinion, not really. We do not use any stream functions, simply replacing the control stream syntax with an API.

If accurate behavior is less important, then there may be more suitable examples, such as Jacques answer.

+2
source

All Articles