Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

A stream "cannot resolve method" that exists

Why doesn’t the problematic line work? The IDE says

Cannot resolve method ‘identify(String[])’"

but it’s right. there

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public class PersonApp {
    public static void main(String[] args) {
        if (areValidArgs(args)) {
            Operations.findAppropriateOperation(args).execute();
        }
    }

    public static boolean areValidArgs(String[] args) {
        return args.length > 0;
    }
}
@Component
public class Operations {
    private static Operation[] operations; // let Spring inject all beans of type Operation
    
    @Autowired
    public void setOperations(Operation[] operations) {
        Operations.operations = operations;
    } 

    public static Operation findAppropriateOperation(String[] args) {
        Optional<Operation> operationOptional = Arrays.stream(operations)
                .findFirst(op -> op.identify(args)); // this line is problematic
/*
If I change the statement above to

        Optional<Operation> operationOptional = Arrays.stream(operations)
                .filter(op -> op.identify(args))
                .findFirst();

it works, but I can't stop thinking why the initial code didn't
*/
        return operationOptional
                .orElseThrow(() -> new IllegalArgumentException("Unsupported argument"));
    }
}
@Component
@RequiredArgsConstructor
public abstract class Operation {
    protected final PersonService personService;

    public abstract boolean identify(String[] args); // here!
    public abstract void execute();
}
// sample operation

@Component
public class CreatePersonTableOperation extends Operation {
    public CreatePersonTableOperation(PersonService personService) {
        super(personService);
    }

    @Override
    public boolean identify(String[] args) {
        return args.length == 1 && args[0].equals("1");
    }

    @Override
    public void execute() {
        personService.createPersonTable();
    }
}

I thought maybe Arrays.stream() returns a stream of Objects (for example, stream.toArray() returns an array of Objects so streams and arrays don’t get along very well), but I checked the docs, and it doesn’t

public static <T> Stream<T> stream(T[] array)

Returns a sequential Stream with the specified array as its source.

Type Parameters:

T – The type of the array elements

Parameters:

array – The array, assumed to be unmodified during use

Returns:

a Stream for the array

>Solution :

While void Operation#identify(String[]) exists, Optional<T> Stream#findFirst(Predicate<? super T>) does not.

Stream#findFirst() is parameterless method.

Since there is no parameter, the Java compiler cannot infer the type of the lambda op parameter. It can only do that if there is a SAM type available to match against.

If you want to find the first item based on a given predicate, you have to filter the stream first:

Optional<Operation> operationOptional = Arrays.stream(operations)
        .filter(op -> op.identify(args))
        .findFirst();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading