Reputation: 3733
private Optional<Example> getTopExample(List<Example> exampleList, String input) {
String lowerCaseInput = input.toLowerCase();
Comparator<Example> exampleNearestMatchComparator = exampleComparator
.thenComparing((Example ex1, Example ex2) -> {
String name1LowerCase = getNameOfExample(ex1).toLowerCase();
String name2LowerCase = getNameOfExample(ex2).toLowerCase();
if (name1LowerCase.startsWith(input) && name2LowerCase.startsWith(lowerCaseInput)) {
return name1LowerCase.length() <= name2LowerCase.length() ? 1 : -1;
} else if (name1LowerCase.startsWith(lowerCaseInput)) {
return 1;
} else if (name2LowerCase.startsWith(lowerCaseInput)) {
return -1;
} else {
if (name1LowerCase.contains(lowerCaseInput) && name2LowerCase.contains(lowerCaseInput)) {
return name1LowerCase.length() <= name2LowerCase.length() ? 1 : -1;
} else if (name1LowerCase.contains(lowerCaseInput)) {
return 1;
} else if (name2LowerCase.contains(lowerCaseInput)) {
return -1;
} else {
return 1;
}
}
});
return exampleList.stream())
.max(exampleNearestMatchComparator);
}
I have a custom Object of type Example , which have properties like name, score etc... I would like to define a method whose purpose is to retrieve the top(mostImportant) Example from List of Example.
Example which has highest 'score' is the top(mostImportant) Example and I already have a comparator called 'exampleComparator' to do that purpose. In some cases, there is chance that two Example have the same score. In that case I would like to choose the Example whose name is nearly close to the 'input'. I created a 'exampleNearestMatchComparator' as you can see in the code.
As you can see, every time 'getTopExample' is invoked a new 'exampleNearestMatchComparator' will create. I would like to define 'exampleNearestMatchComparator' outside this method but as you can see 'exampleNearestMatchComparator' depends on a dynamic 'input' ( which can change on every invocation of getTopExample). As per my understanding, lambdas in streams are ' closed over values rather than variable' (http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html), I could not define 'exampleNearestMatchComparator' outside this method.
Am I correct? Any suggestions are welcome.
Upvotes: 0
Views: 39
Reputation: 4555
If you want to prevent to re-create the nearest match comparator every time, you could make input
, lowerCaseInput
, and the comparator
fields that you update before you use the comparator:
private Comparator<Example> exampleComparator = // your comparator;
private String input;
private String lowerCaseInput;
private Comparator<Example> nearestMatchComparator = // your lambda;
private Comparator<Example> exampleNearestMatchComparator = exampleComparator.thenComparing(nearestMatchComparator);
private Optional<Example> getTopExample(List<Example> exampleList, String input)
{
this.input = input;
this.lowerCaseInput = input.toLowerCase();
return exampleList.stream().max(exampleNearestMatchComparator);
}
It might be nicer, though, to wrap the lambda into a separate class which has a setter for the input
.
private Comparator<Example> exampleComparator = // your comparator;
private Comparator<Example> nearestMatchComparator = new NearestMatchComparator();
private Comparator<Example> exampleNearestMatchComparator = exampleComparator.thenComparing(nearestMatchComparator);
private Optional<Example> getTopExample(List<Example> exampleList, String input)
{
nearestMatchComparator.setInput(input);
return exampleList.stream().max(exampleNearestMatchComparator);
}
private final class NearestMatchComparator
implements Comparator<Example>
{
private String input;
private String lowerCaseInput;
public void setLowerCaseInput(String input)
{
this.input = input;
this.lowerCaseInput = input.toLowerCase();
}
@Override
public int compare(Example ex1, Example ex2)
{
// your implementation
}
}
Upvotes: 1