0

what would be most optimal way to rewrite this iteration with java 8 stream().

for (name : names){
  if(name == a){
    doSomething();
    break;
  }
  if(name == b){
   doSomethingElse();
   break; 
 }
 if(name == c){
  doSomethingElseElse();
  break;
 }
}

Basically, iterating over the list with 3 conditions if any of them is satisfied want to break loop and in every condition want to call different method.

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
AriseEVE
  • 49
  • 2
  • 8
  • 6
    This code will not do what you think it does; use `equals` to compare strings instead of `==`. See: [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – Jesper Dec 13 '16 at 08:30
  • 1
    Your "basically" doesn't describe what you're doing, as you're *also* calling a different method for each of those three conditions. Why do you *want* to rewrite this to use `stream()`? It doesn't look like it fits very naturally. – Jon Skeet Dec 13 '16 at 08:33
  • I'm just wondering if it is possible to do it with stream() in single iteration. – AriseEVE Dec 13 '16 at 08:37
  • Your code does not need iteration at all. Just use `contains` – ZhekaKozlov Dec 13 '16 at 08:57

3 Answers3

6

You can use anyMatch to find the first element matching one of your conditions and terminate. Use side effects for calling the processing methods :

boolean found =
  names.stream()
       .anyMatch (name -> {
                  if (name.equals(a)) {
                    doSomething();
                    return true;
                  } else if (name.equals(b)) {
                    doSomethingElse ();
                    return true;
                  } else if (name.equals(c)) {
                    doSomethingElseElse ();
                    return true;
                  } else {
                    return false;
                  }
                }
              );

Pretty ugly, but does what you asked in a single iteration.

Eran
  • 387,369
  • 54
  • 702
  • 768
5

The answer by Eran is definitely the straightforward way of performing the search. However, I would like to propose a slightly different approach:

private static final Map<String, Runnable> stringToRunnable = new HashMap<>();

{
  stringToRunnable.put("a", this::doSomething);
  stringToRunnable.put("b", this::doSomethingElse);
  stringToRunnable.put("c", this::doSomethingElseElse);
}

public static void main(String[] args) {
  List<String> names = Arrays.asList("1", "2", "b", "a");
  names.stream()
      .filter(stringToRunnable::containsKey)
      .findFirst()
      .ifPresent(name -> stringToRunnable.get(name).run());
}

private void doSomethingElseElse() {
}

private void doSomethingElse() {
}

public void doSomething() {
}

The part that does the job is the code below, but I added it to a main() function assuming a, b, and c are strings. However, the idea would work with any datatype.

names.stream()
    .filter(stringToRunnable::containsKey)
    .findFirst()
    .ifPresent(name -> stringToRunnable.get(name).run());

The idea is to keep a map of keys and Runnables. By having Runnable as value it is possible to define a void method reference without parameters. The stream first filters away all values not present in the map, then finds the first hit, and executes its method if found.

Community
  • 1
  • 1
Magnilex
  • 11,584
  • 9
  • 62
  • 84
-2
Collection collection;
collection.forEach(name->{
    if(name.equals(a))){
       doSomething();

    }
    if(name.equals(b)){
        doSomethingElse();

    }
    if(name.equals(c)){
        doSomethingElseElse();

    }
});
  • 1
    I want the loop to brake if it enters in any of the if statements, because only single If could be possible true for every list. – AriseEVE Dec 13 '16 at 08:40