问题
I have filter personCountFilter=3, and have list as below:
Rate{ PersonCount:1, LOS:1}
Rate{ PersonCount:1, LOS:2}
Rate{ PersonCount:1, LOS:3}
Rate{ PersonCount:2, LOS:1}
Rate{ PersonCount:2, LOS:2}
Rate{ PersonCount:2, LOS:3}
Rate{ PersonCount:3, LOS:2}
Rate{ PersonCount:3, LOS:4}
Rate{ PersonCount:3, LOS:5}
Rate{ PersonCount:3, LOS:6}
Rate{ PersonCount:4, LOS:3}
Rate{ PersonCount:5, LOS:7}
Rate{ PersonCount:6, LOS:7}
After filter my expected:
Rate{ PersonCount:2, LOS:1}
Rate{ PersonCount:3, LOS:2}
Rate{ PersonCount:4, LOS:3}
Rate{ PersonCount:3, LOS:4}
Rate{ PersonCount:3, LOS:5}
Rate{ PersonCount:3, LOS:6}
Rate{ PersonCount:5, LOS:7}
how can I get value after grouping by LOS, and if personCount matched filter get this one, if not matched, get closest to personCountFilter, bigger personCountFilter first
I tried to use
HashSet<Rate> testSet = rates.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Rate::getLengthOfStayCount,
Function.identity(),
(previous, current) ->
{
return previous.getPersonCount() >
current.getPersonCount() ? previous : current;
}),
map ->
{
HashSet<Rate> set = new HashSet<>();
set.addAll(map.values());
return set;
}));
but it returns
Rate{ PersonCount:2, LOS:1}
Rate{ PersonCount:3, LOS:2}
Rate{ PersonCount:4, LOS:3}
Rate{ PersonCount:3, LOS:4}
Rate{ PersonCount:3, LOS:5}
Rate{ PersonCount:3, LOS:6}
Rate{ PersonCount:6, LOS:7}
Current it gets max personCount when after grouping by LOS
回答1:
I was unable to test the following code with the information you have provided in the question (learn how to make a Minimal, Complete, and Verifiable example for your next question), but I think something like this should work for you:
HashSet<Rate> testSet = rates.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Rate::getLengthOfStayCount,
Function.identity(),
(previous, current) ->
{
int diff1 = Math.abs(personCountFilter - previous.getPersonCount());
int diff2 = Math.abs(personCountFilter - current.getPersonCount());
if (diff1 > diff2) {
return current;
} else if (diff1 < diff2) {
return previous;
} else if (diff1 == diff2) {
return previous.getPersonCount() <= current.getPersonCount() ? current : previous;
}
}),
map -> new HashSet<>(map.values())
));
回答2:
If I understand you correctly, you want to get the element of each group, which has the personCount property closest to the number 3, with preference to the higher number in case of a tie.
You may achieve it using
HashSet<Rate> testSet = rates.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Rate::getLengthOfStayCount,
Function.identity(),
BinaryOperator.minBy(
Comparator.comparingDouble(rate -> Math.abs(rate.getPersonCount()-3.1)))
),
map -> new HashSet<>(map.values())
));
Math.abs(rate.getPersonCount()-3) is the distance to your goal number 3, getting the element with the minimum of that value will get the closest. By simply using 3.1 instead of 3, we achieve preference to higher numbers in case of a tie (assuming that you property has an integer type).
来源:https://stackoverflow.com/questions/44003534/how-can-i-get-value-through-complex-logic-from-list