Проверка содержания в наборе строк в Java - PullRequest
9 голосов
/ 26 ноября 2010

У меня есть набор строк []. Я хочу проверить, содержит ли этот набор другую строку [].

Set<String[]> s  = new HashSet<String[]>();
s.add(new String[] {"lucy", "simon"});
System.out.println(s.contains(new String[] {"lucy", "simon"}));

Однако false печатается. Я думаю, это потому, что сравниваются только ссылки, а не фактические строки. Кажется, единственный вариант, который у меня есть, - создать класс, скажем, Phrase, и реализовать hashCode() и equals() (которые используют Arrays.hashCode(...)).

Есть ли другой способ добиться того, чего я хочу?

Ответы [ 7 ]

13 голосов
/ 26 ноября 2010

Ваше предположение верно: массивы ([]) не реализуют метод глубокого равенства: они равны, если они являются одним и тем же экземпляром.

Самое простое решение: замена String[] на List<String>

Другим способом (но я не рекомендую его) является реализация собственного набора, который основан не на Object.equals, а на java.util.Arrays.equals(Object[]a, Object[]b)

11 голосов
/ 26 ноября 2010

Преобразуйте это String[] в List<String>, и оно должно получиться довольно хорошо.

Set<List<String>> s  = new HashSet<List<String>>();
s.add(Arrays.asList("lucy", "simon"));
System.out.println(s.contains(Arrays.asList("lucy", "simon")));
3 голосов
/ 26 ноября 2010

Могут ли элементы строки [] быть в разных порядках и при этом сделать весь массив равным другому массиву, содержащему те же элементы в другом порядке?Если да, то вам действительно лучше реализовать класс контейнера и переопределить equals и hashcode.

, если нет, и если приемлемым вариантом является хранение внутренних элементов в виде списков вместо массивов, то вы можете сделать это:

package com.stackoverflow;


import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class StringContainment {

  public static void main(final String[] args) {
    final Set<String[]> s = new HashSet<String[]>();
    final Set<List<String>> s2 = new HashSet<List<String>>();

    s.add(new String[] {"lucy", "simon"});
    s2.add(Arrays.asList(new String[] { "lucy", "simon" }));

    System.out.println(s.contains(new String[] {"lucy", "simon"})); // false
    System.out.println(s2.contains(Arrays.asList(new String[] {"lucy", "simon"}))); // true
  }

}

Первая проверка вернет false, вторая - true.Так может быть проще, если вы можете использовать списки.

Если вы не можете, вы можете использовать это до тех пор, пока вам не нужно делать это сравнение слишком часто (это определенно не очень хорошая идея.-wise).

1 голос
/ 26 ноября 2010

Похоже, вы уже ответили на свой вопрос.Один вариант, как вы уже заявили.Другой вариант - использовать Set> , поскольку API для equals (Object) говорит:

Сравнивает указанный объект с этой коллекцией на равенство.

1 голос
/ 26 ноября 2010

Используйте Set<Set<String>> или Set<List<String>> вместо Set<String[]>

Код:

List<String> s1=Arrays.asList("1","2"),s2=Arrays.asList("1","2");
System.out.println(s1.equals(s2) + " "+s1.hashCode()+ " "+s2.hashCode());

Выход:

true 2530 2530
0 голосов
/ 06 марта 2018

С потоком Java8 вы можете сделать это следующим образом:

Boolean res = s.stream()
  .anyMatch(elm -> elm.equals("lucy") || elm.equals("simon"));
0 голосов
/ 26 ноября 2010

Я бы просто перебрал и вызвал Arrays.equals:

как то так:

boolean contains(Set<String[]> s, String[] item) {
  for(String[] toCompare: s) {
    if(Arrays.equals(toCompare, item)) {
        return true;
    }
  }
  return false;
}

не уверен, что он самый быстрый, но он должен хорошо выполнять свою работу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...