Java - лучший способ сохранить уникальный список массива строк

1

У меня есть список массивов строк, которые могут иметь повторяющиеся записи. Я хочу получить уникальный список из этих значений.

У меня есть список массивов строк с каждым массивом, имеющим два значения String.

Примеры значений массива строк:

{"error message 1", "fail"}
{"error message 2", "N/A"}
{"error message 1", "fail"} // duplicate
{"error message 2", "fail"}

Я получаю строки "error message 1" и "fail" из элементов JSON отдельно и добавляю их к объекту массива String. Теперь я хочу уникальную комбинацию этого массива. Итак, если у меня было выше 4 массивов, я хочу иметь список из трех уникальных записей.

Из поиска в Интернете я развернулся, чтобы использовать HashSet для моего варианта использования (порядок не имеет значения). Тем не менее, HashSet добавляет все 4 записи в набор. Я даже пытался использовать " contains ", чтобы проверить, существует ли объект, но это тоже не сработало. Я считаю, это потому, что метод contains сравнивает " reference ", а не " value ". Является ли это причиной того, что HashSet добавляет повторяющиеся значения?

Мой код для добавления этих массивов String в HashSet

Set<String[]> uniqueSet = new HashSet<String[]>();
if(!uniqueSet.contains(new String[] {errorMessage,result})) // I get errorMessage and result as separate Strings
   uniqueSet.add(new String[] {errorMessage,result}); // I expect to have only 3 values here in the uniqueSet. But it adds all 4.

Из ответов на связанные вопросы по SO я понимаю, что хэш-код и равные методы должны быть перезаписаны, если это необходимо. Но, я не уверен, как мне это сделать в моем случае, если это то, чего я не хватает?

Кроме того, дайте мне знать, если у вас есть другие предложения, чтобы лучше хранить массивы String однозначно.

С Уважением,

Rumit

  • 0
    это должна быть строка []? , вы можете конвертировать String [] в POJO и затем реализовать .equals.?
  • 0
    Я написал бы эти уникальные записи в файл CSV, используя библиотеку openCSV, которая принимает String [].
Теги:
string
arrays
collections

4 ответа

7
Лучший ответ

Вы можете использовать List вместо массивов. Если вы используете списки из пакета java.util, они должны уже реализовать hashCode() и equals(Object) таким образом, который соответствует вашим потребностям (глубокие равенства и глубокий hasCode):

String[][] stringArrays = new String[][] {
    {"error message 1", "fail"},
    {"error message 2", "N/A"},
    {"error message 1", "fail"}, // duplicate
    {"error message 2", "fail"}
};

Set<List<String>> uniqueSet = new HashSet<List<String>>();
for (String[] a : stringLists) {
    uniqueSet.add(Arrays.asList(a));
}
// uniqueSet.size() should return 3 here
  • 0
    Оно работает! Спасибо!
1

Поскольку Java не имеет кортежей, одним из способов его решения будет использование кортежа -

class Pair<L,R> {

    private final L left;
    private final R right;


    Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    L getLeft() {
        return left;
    }

    R getRight() {
        return right;
    }

    @Override
    public int hashCode() { return left.hashCode() ^ right.hashCode(); }

    @Override
    public boolean equals(Object o) {
        if (o == null) return false;
        if (!(o instanceof Pair)) return false;
        Pair pairo = (Pair) o;
        return this.left.equals(pairo.getLeft()) &&
                this.right.equals(pairo.getRight());
    }

}
  • 0
    Почему название «ключ»? Разве нельзя иметь две пары с одним и тем же ключом?
0

Вместо использования Set<String[]> создайте новый класс, например:

public class MyError {
    private String message;
    private String detail;

    //constructors, getters and setters

    public boolean equals(Object other) {
        //implement equals here - i suggest you to use an IDE auto generated equals()
    }
}

И используйте Set<MyError>. Итак, когда вы это сделаете:

uniqueSet.add(new MyError(errorMessage, result));

он будет подавлять дублированные записи правильно из-за реализации равных.

0

Я не знаю, подходит ли оно вашим потребностям, но (по крайней мере) более быстрое решение будет использовать HashMap.

HashMap<String, String> hashMap = new HashMap<String, String>();

hashMap.put("error message 1","fail");
hashMap.put("error message 2","fail");
hashMap.put("error message 1","N/A");

Результатом будет только два элемента в списке, поскольку элемент Key (в этом случае "сообщение об ошибке 1") будет перезаписан следующим, который вы ввели в список.

Результат:

hashMap=[{"error message 1","N/A"},{"error message 2","fail"}];
  • 0
    Я не могу перейти на карту, поскольку уникальность должна сочетаться с «errormessage» и «result». Итак, мой ключ - это комбинация двух строк.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню