Oleksandr
Oleksandr

Reputation: 818

Java stream type issue

Somehow I can't use check on instanceof in stream. The problem occurred in test:

ArgumentCaptor<MyClass> arg = ArgumentCaptor.forClass(MyClass.class);
verify(modelService).save(arg.capture());

Method save called three times with different arguments(instances of different classes), and arg.getAllValues() returned SomeOtherClassObject1,SomeOtherClassObject2,MyClassObject

Stream bellow throws exception "SomeOtherClass can not be cast to MyClass"

MyClass argument = arg.getAllValues().stream()
.filter(v -> v instanceof MyClass)
.findFirst()
.get()

But if I use foreach everything works fine:

MyClass argument = null;
for(Object o : arg.getAllValues()) {
    if(o instanceof MyClass) {
        argument = (MyClass) o;
        break;
    }
}

Upvotes: 0

Views: 124

Answers (2)

Andy Turner
Andy Turner

Reputation: 140309

The for each loop example shown in the question contains an explicit cast after the instanceof check. The following would be equivalent to that loop:

MyClass argument =
    arg.getAllValues()
        .stream()                            // Stream<SomeOtherClass>
        .filter(v -> v instanceof MyClass)   // Stream<SomeOtherClass>
        .map(MyClass.class::cast)            // Stream<MyClass>
        .findFirst()                         // Optional<MyClass>
        .orElse(null);                       // MyClass

Upvotes: 1

drowny
drowny

Reputation: 2147

Try with this casting. Because filter only filtering the stream according to your checking rule. This is one solution to resolve problem. Or use map to cast.

MyClass argument = ((MyClass)arg.getAllValues()
    .stream().
    .filter(v -> v instanceof MyClass)
    .findFirst()
    .get());

PS: map is more relevant to if your results more than one to apply for all. In your problem casting is more appropriate

Upvotes: 1

Related Questions