【问题标题】:Create unique list of objects by any property按任何属性创建唯一的对象列表
【发布时间】:2019-08-08 12:17:25
【问题描述】:

我正在尝试创建具有List 行为的通用类,但接受StringField 作为应该确定唯一性的属性名称。 例如我们有类User:

public class User {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

我想上课让我们说名字UniqueList。 并且能够提供给构造函数User.class.getDeclaredField("name"),这将使这个用户列表通过用户的属性名称是唯一的,并且这个列表将不能包含两个名为“John”的用户对象。

至于现在,我尝试创建扩展 ArrayList<T> 并实现 Set<T> 的类,但我开始在逻辑上弄得一团糟。 也许有人已经有了类似的东西,可以分享或帮助理解如何实现它。 目前我拥有的代码:

public class UniqueValueList<T> extends ArrayList<T> implements Set<T> {

    private String uniqueValueKey;
    private Field keyField;
    HashMap<Object, T> hashMap;

    public UniqueValueList(Class c, String keyName) {
        hashMap = new HashMap<>();
        try {
            keyField = c.getDeclaredField(keyName);
            keyField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean add(T t) {
        try {
            //get value of the key from provided object.
            Object keyValue = keyField.get(t);
            if (hashMap.containsKey(keyValue)) {
                hashMap.remove(keyValue);
            }
            hashMap.put(keyValue, t);
            super.add(t);
            return true;
        } catch (IllegalAccessException | NullPointerException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        return super.addAll(c);
    }

    @Override
    public boolean remove(Object o) {
        return super.remove(o);
    }

    @Override
    public void clear() {
        super.clear();
    }

    @Override
    public boolean contains(Object o) {
        return super.contains(o);
    }
}

【问题讨论】:

  • 我认为与其扩展 ArrayList 并同时实现 Set ,不如只扩展 ArrayList 并覆盖其 add 方法。检查列表是否包含 list.contains(data) 如果不包含则仅将其添加到列表中,这将有助于独特性。
  • 这是常规方式,我必须为此进行嵌套 for 循环,我试图避免它。这就是我实施 set 的原因
  • 然后你可以使用 LinkedHashset。从而保持顺序和唯一性。

标签: java generics arraylist set


【解决方案1】:

您的逻辑似乎是正确的。替换时不要忘记从列表中删除对象:

    @Override
    public boolean add(T t) {
        try {
            //get value of the key from provided object.
            Object keyValue = keyField.get(t);
            if (hashMap.containsKey(keyValue)) {
                super.remove(hashMap.get(keyValue)); // << remove old object from list
                hashMap.remove(keyValue);
            }
            hashMap.put(keyValue, t);
            super.add(t);
            return true;
        } catch (IllegalAccessException | NullPointerException e) {
            e.printStackTrace();
        }
        return false;
    }

相应地覆盖其他添加/删除方法。请记住,ArrayList 扩展了 List,因此您还需要覆盖 ArrayList 的添加/删除方法(例如 add(int index, E element)remove(int index) 等)

【讨论】:

    猜你喜欢
    • 2013-09-17
    • 2013-06-25
    • 2011-10-25
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    相关资源
    最近更新 更多