Создать уникальный список объектов по любому свойству - PullRequest
0 голосов
/ 18 марта 2019

Я пытаюсь создать общий класс, который будет иметь поведение List, но примет Field из String в качестве имени свойства, которое должно определять уникальность.Например, у нас есть класс 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"), этот список пользователей будет уникальным по имени свойства пользователя, и этот список не сможет содержать два объекта пользователя с именем «Джон», например.

На данный момент я попытался создать класс, который расширяет 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);
    }
}

1 Ответ

0 голосов
/ 18 марта 2019

Ваша логика кажется правильной. Не забудьте удалить объект из списка при замене:

    @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) и т. Д.)

...