how to convert forEach to lambda

南楼画角 提交于 2019-12-01 09:38:31

问题


Iterator<Rate> rateIt = rates.iterator();
int lastRateOBP = 0;
while (rateIt.hasNext())
{
    Rate rate = rateIt.next();
    int currentOBP = rate.getPersonCount();
    if (currentOBP == lastRateOBP)
    {
        rateIt.remove();
        continue;
    }

    lastRateOBP = currentOBP;
}

how can i use above code convert to lambda by stream of java 8? such as list.stream().filter().....but i need to operation list.


回答1:


If you really want distinct and sorted as you say in your comments, than it is as simple as :

TreeSet<Rate> sorted = rates.stream()
                  .collect(Collectors.toCollection(() -> 
                   new TreeSet<>(Comparator.comparing(Rate::getPersonCount))));

But notice that in your example with an iterator you are not removing duplicates, but only duplicates that are continuous (I've exemplified that in the comment to your question).

EDIT

It seems that you want distinct by a Function; or in simpler words you want distinct elements by personCount, but in case of a clash you want to take the max pos.

Such a thing is not yet available in jdk. But it might be, see this.

Since you want them sorted and distinct by key, we can emulate that with:

 Collection<Rate> sorted = rates.stream()
            .collect(Collectors.toMap(Rate::getPersonCount,
                    Function.identity(),
                    (left, right) -> {
                        return left.getLos() > right.getLos() ? left : right;
                    },
                    TreeMap::new))
            .values();

    System.out.println(sorted);

On the other hand if you absolutely need to return a TreeSet to actually denote that this are unique elements and sorted:

 TreeSet<Rate> sorted = rates.stream()
            .collect(Collectors.collectingAndThen(

                    Collectors.toMap(Rate::getPersonCount,
                            Function.identity(),
                            (left, right) -> {
                                return left.getLos() > right.getLos() ? left : right;
                            },
                            TreeMap::new),
                    map -> {
                        TreeSet<Rate> set = new TreeSet<>(Comparator.comparing(Rate::getPersonCount));
                        set.addAll(map.values());
                        return set;
                    }));



回答2:


The simplest solution is

Set<Integer> seen = new HashSet<>();
rates.removeIf(rate -> !seen.add(rate.getPersonCount()));

it utilizes the fact that Set.add will return false if the value is already in the Set, i.e. has been already encountered. Since these are the elements you want to remove, all you have to do is negating it.

If keeping an arbitrary Rate instance for each group with the same person count is sufficient, there is no sorting needed for this solution.

Like with your original Iterator-based solution, it relies on the mutability of your original Collection.




回答3:


This should work if your Rate type has natural ordering (i.e. implements Comparable):

List<Rate> l = rates.stream()
                             .distinct()
                             .sorted()
                             .collect(Collectors.toList());

If not, use a lambda as a custom comparator:

List<Rate> l = rates.stream()
                             .distinct()
                             .sorted( (r1,r2) -> ...some code to compare two rates... )
                             .collect(Collectors.toList());

It may be possible to remove the call to sorted if you just need to remove duplicates.



来源:https://stackoverflow.com/questions/43973596/how-to-convert-foreach-to-lambda

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!