-1

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

Holger
  • 285,553
  • 42
  • 434
  • 765
Haven Lin
  • 176
  • 1
  • 16
  • 2
    Could you make question more clear.. I dont understand what is expected : to be precise, I dont understand " and if personCount matched filter get this one, if not matched, get most near with personCountFilter, bigger personCountFilter first" – Vivek Sachdeva May 16 '17 at 14:07
  • sos, help https://stackoverflow.com/questions/44178932/code-compiler-error-between-ide-language-level-7-and-8 – Haven Lin May 25 '17 at 11:04

2 Answers2

0

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())
                    ));
Robin Topper
  • 2,295
  • 1
  • 17
  • 25
0

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).

Holger
  • 285,553
  • 42
  • 434
  • 765