Найти уникальные записи в списке <Object []> - PullRequest
3 голосов
/ 30 января 2012
List<Object> listObj = new ArrayList<Object[]>();
listObj.add(new Object[]{1,"abc",new Date(21/1/2001)});
listObj.add(new Object[]{1,"abc",new Date(21/1/2001)});
listObj.add(new Object[]{2,"acc",new Date(21/1/2001)});
Set<Object[]> unique = new HashSet<Object[]>();
unique.addAll();

Я ожидаю получить:

{1,abc,21/1/2001},{2,acc,21/1/2001}

Вместо этого я получаю:

{1,abc,21/1/2001},{1,abc,(21/1/2001},{2,acc,21/1/2001}

Как найти уникальные записи в этом примере?

Ответы [ 6 ]

6 голосов
/ 30 января 2012

Массивы в Java не имеют концепции равенства, которая позволила бы этому работать. Вам нужно определить пользовательский класс с числом, строкой и датой и самостоятельно реализовать equals / hashCode, чтобы это работало.

1 голос
/ 30 января 2012

Вы можете использовать TreeSet, инициализированный с пользовательским Comparator, который выполняет необходимую проверку;нет никакой возможности для этой работы с массивами и компаратором по умолчанию.

0 голосов
/ 30 января 2012

Вы могли бы реализовать тонкую оболочку вокруг Object[], которая обеспечивала бы соответствующие hashCode() и equals(). Два метода могут быть очень легко реализованы в терминах Arrays.deepHashCode() и Arrays.deepEquals():

public class Cmp {

    public static class ObjArray {
        private final Object[] arr;
        public ObjArray(Object[] arr) {
            this.arr = arr;
        }
        @Override
        public int hashCode() {
            return Arrays.deepHashCode(arr);
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            ObjArray other = (ObjArray)obj;
            return Arrays.deepEquals(arr, other.arr);
        }
    }

    public static void main(String args[]) {
        List<ObjArray> listObj = new ArrayList<ObjArray>();
        listObj.add(new ObjArray(new Object[]{1,"abc",new Date(21/1/2001)}));
        listObj.add(new ObjArray(new Object[]{1,"abc",new Date(21/1/2001)}));
        listObj.add(new ObjArray(new Object[]{2,"acc",new Date(21/1/2001)}));
        Set<ObjArray> unique = new HashSet<ObjArray>();
        unique.addAll(listObj);
        System.out.println(unique);
    }


}
0 голосов
/ 30 января 2012

Массивы в Java не переопределяют hashCode() и equals(), поэтому сравнение двух массивов с одинаковым содержимым (с одинаковой длиной и одинаковыми элементами) неожиданно приводит к значению false.

Если вы используете List<Object>, оно должно работать нормально. Вы можете воспользоваться утилитой Arrays.asList().

0 голосов
/ 30 января 2012

Я бы инкапсулировал все данные в массиве объектов в POJO.В POJO вы можете определить свой собственный метод равно .например,

public class Bean {
    private int i;
    private String l;
    private Date d;
    public int getI() {
        return i;
    }
    public void setI(int i) {
        this.i = i;
    }
    public String getL() {
        return l;
    }
    public void setL(String l) {
        this.l = l;
    }
    public Date getD() {
        return d;
    }
    public void setD(Date d) {
        this.d = d;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((d == null) ? 0 : d.hashCode());
        result = prime * result + i;
        result = prime * result + ((l == null) ? 0 : l.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof Bean))
            return false;
        Bean other = (Bean) obj;
        if (d == null) {
            if (other.d != null)
                return false;
        } else if (!d.equals(other.d))
            return false;
        if (i != other.i)
            return false;
        if (l == null) {
            if (other.l != null)
                return false;
        } else if (!l.equals(other.l))
            return false;
        return true;
    }
}
0 голосов
/ 30 января 2012

Самый простой подход - использовать Set.Я настоятельно рекомендую создать класс для захвата вашего объекта int, string и date

public class Foo {
    private int num;
    private String letters;
    private Date date;
}

Затем вы можете переопределить методы equals и hashCode, чтобы получить ожидаемое поведение из вашего набора

...