问题
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