根据条件创建地图,从列表中去除重复项。

5
我想基于Java 8的Lambda表达式,通过条件获取一个不包含重复项的列表。假设我有以下代码:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {

    class Person {
        private String name;
        private int age;

        public Person(String name, int age) {
           this.name = name;
           this.age = age;
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return this.age;
        }

        public void setName(int age) {
            this.age = age;
        }
    }

    public static void main(String[] args) {

        Main main = new Main();
        main.createList();
    }

    public void createList() {

        List<Person> p = new ArrayList<Person>();
        p.add(new Person("william", 34));
        p.add(new Person("billie", 62));
        p.add(new Person("Loise", 37));
        p.add(new Person("Margot", 12));
        p.add(new Person("billie", 63));
        p.add(new Person("billie", 61));

        System.out.println("show People initially");
        show(p);

        // It's going to be duplicated when it has the same name
        // It'll keep the older person. For example, for billie it should keep billie -> 63

        p = removeDuplicate(p, person -> buildPersonKey(person));

        System.out.println("show People After");
        show(p);

    }

    public void show(List<Person> pList) {
        for (Person p: pList) {
            System.out.println(p.getName() + "-Age: " + p.getAge());
        }
    }



    public <T> List<T> removeDuplicate(List<T> dataList, Function<? super T, ?> keyFunction) {
        return
                new ArrayList<>(dataList.stream()
                        .collect(Collectors.toMap(
                                p -> (keyFunction.apply(p)),
                                p -> p,
                                (oldValue, newValue) -> newValue))  
                        .values());
    }

    public String buildPersonKey(Person p) {
        return p.getName();
    }
}

这是我的当前输出:

show People initially
william-Age: 34
billie-Age: 62
Loise-Age: 37
Margot-Age: 12
billie-Age: 63
billie-Age: 61
show People After
william-Age: 34
billie-Age: 61 // Here I want "billie-Age: 63"
Loise-Age: 37
Margot-Age: 12

这行代码 (oldValue, newValue) -> newValue)) 是关键,但我需要的是一个if表达式,类似于mapValueOld.getAge() > mapValueNew.getAge() ? mapValueOld.getAge() : mapValueNew.getAge()

你有什么想法吗?谢谢。


1
最好使用 (a,b) -> a.getAge() > b.getAge()? a: b,因为您不想映射到年龄,而是选择其中一个传入元素,基于年龄进行选择。但是,您不能在具有任意 <T> 的通用方法中执行此操作,因为 T 没有 getAge() 方法。您需要使用带有边界的类型变量或不要使该方法成为通用方法。或者将合并函数作为参数,以便调用方可以提供实际的 T 类型。 - Holger
你可以使用 Collection.removeIf() - dehasi
1个回答

4

由于您的removeDuplicate方法是通用的,因此您需要向其传递一个函数来选择具有相同键的两个元素之间的差异:

public <T> List<T> removeDuplicate(List<T> dataList, Function<? super T, ?> keyFunction, BinaryOperator<T> chooser) {
    return
            new ArrayList<>(dataList.stream()
                    .collect(Collectors.toMap(keyFunction,
                                              Function.identity(),
                                              chooser))
                    .values());
}

并使用以下方式调用该方法:

p = removeDuplicate(p,
                    person -> buildPersonKey(person),
                    (p1,p2) -> p1.getAge() >= p2.getAge() ? p1 : p2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接