I might have misunderstood what the code of @zond should produce, but the principle stays the same. So this code might reverse conditions (returns "OK" first and then "ERROR" instead of the other way round).
if (searchValueInStream(src, "ERROR")) {
return "ERROR";
} else if (searchValueInStream(src, "OK")) {
return "OK";
}
return "NA";
The problem with your code is that you're running through the list twice, once for the "ERROR" search, once for the "OK" search. This can be a costly operation (though, it most likely is not).
I'm not on good terms with streams (I believe they are overhyped and rarely reduce complexity/cognitive load) so I can only provide you with an example without them. What you want is to loop once through the list and keep state for this time. The most simple solution would be something like this:
boolean errorEncountered = false;
for (String item : items) {
if (item.equals("OK")) {
return "OK";
} else if (item.equals("ERROR")) {
errorEncountered = true;
}
}
if (errorEncountered) {
return "ERROR";
} else {
return "NA";
}
In the best case the loop exits at the first item, as it is "OK", the worst case is that it loops through the whole list once.
However, this approach has two problems:
- If you want the
item
itself, you need to store that.
- With more items this becomes quite cumbersome.
The first point is rather easily solved:
Item firstEncounteredErrorItem = null;
for (Item item : items) {
if (item.getState().equals("OK")) {
return item;
} else if (firstEncounteredErrorItem == null && item.getState().equals("ERROR")) {
firstEncounteredErrorItem = item;
}
}
if (firstEncounteredErrorItem != null) {
return firstEncounteredErrorItem;
} else {
return Item.NA;
}
A little bit more complex, but still quite manageable.
Now, the second point, extensibility, is harder to solve, as we may need to "stack" differently prioritized items. For that, we'd require something like "Tuple", which we most likely need to write ourselves. The basic idea would be keeping a List
of encountered items which match their "priorization".
List<String> prioritziedItemStates = Item.PRIORITIZED_ITEM_STATES;
Item[] encounteredItems = new Item[Item.MAX_VALUE_COUNT];
for (Item item : items) {
if (item.getState().equals("OK")) {
return item;
} else {
int itemPrioritizedIndex = prioritziedItemStates.indexOf(item.getState());
if (encounteredItems[itemPrioritizedIndex] == null) {
encounteredItems[itemPrioritizedIndex] = item;
}
}
}
for (Item encounteredItem : encounteredItems) {
if (encounteredItem != null) {
return encounteredItem;
}
}
return Item.NA;
This has still the upside that it runs through the list only once, but does a lookup for every item in another (short?) list that is not "OK". Whether that trade is worth it or not is depending on how large the original list is and how many states you need to keep.
String result = results.stream()
.someFilter(v->v.equals(ERROR)? return "ERROR")
.someFilter(v->v.equals(OK)? return "OK")
.orElse("NA");
I'm not sure that's possible with streams, at least not without wrapping them multiple times. There is findFirst
but that terminates the stream, but you want to keep going. Basically what you want would be something like this:
String result = results.stream()
.takeFirstOrElseContinue(result -> result.equals("OK"))
.takeFirstOrElseContinue(result -> result.equals("ERROR"))
.orElse("NA");
I'm not aware that streams would work like that.