Простой вопрос: вывод нижеприведенной Java-программы - PullRequest
4 голосов
/ 28 апреля 2010
public class abc1 {

 private String s;

 public abc1(String s){this.s=s;}
 public static void main(String args[])
 {
  HashSet<Object> hs=new HashSet<Object>();
  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");
  String s1= new String("abc");
  String s2= new String("abc");
  hs.add(a1);
  hs.add(a2);
  hs.add(s1);
  hs.add(s2);
  System.out.println(hs.size());

 }
}

Почему вывод программы выше 3?

Редактировать

Смотри ниже комментарии, я расширяю свой вопрос:

System.out.println (s1 == s2);

s1 и s2 относятся к одному и тому же объекту? Если тогда приведенное выше выражение должно вывести true, но его вывод - false.

Они похожи с точки зрения хэш-кода, но все же различаются?

Ответы [ 8 ]

10 голосов
/ 28 апреля 2010

Существует два неравных экземпляра abc1 (обратите внимание, что он не переопределяет equals или hashCode) и одну строку в наборе. Давайте посмотрим на четыре add звонка:

hs.add(a1);

Изначально набор пуст, поэтому очевидно, что это добавит значение.

hs.add(a2);

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

hs.add(s1);

Это добавит значение к набору, так как строка не равна ни одному из текущих значений (которые не являются строками).

hs.add(s2);

Это не добавляет что-либо к набору, так как вторая строка равна первой. (Строка переопределяет equals / hashCode.)

В результате получается набор из трех предметов.

2 голосов
/ 28 апреля 2010

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

Теперь вы можете быть одурачены тем, что оба a1 и a2 равны, но если они не переопределяют equals или hashCode, то для Java они не равны , Однако с вашими строками s1 и s2 они действительно равны, потому что реализация String уже переопределяет методы equals и hashCode. Попробуйте сделать s1.equals(s2), и вы получите true в результате. Если вы сделаете a1.equals(a2), вы получите false.

В конце ваш хэш-сет содержит a1, a2 и s1.

Вы расширили свой вопрос, чтобы ответить на него ...

s1 и s2 - это , а не , относящиеся к одному и тому же объекту, это два разных объекта String, но оба представляют один и тот же набор символов. Поскольку они не являются одним и тем же объектом, System.out.println(s1 == s2) печатает false. Это equal(), но не один и тот же объект.

1 голос
/ 28 апреля 2010

Вот проблема:

String s1= new String("abc");
String s2= new String("abc");

Можно попробовать сделать:

System.out.println (s1 == s2);

и вы видите true. Набор не может содержать одинаковые объекты, поэтому там хранится только s2.

0 голосов
/ 28 апреля 2010

С учетом

  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");

a1! = A2, поскольку вы не предоставили переопределенный equals(), который будет указывать, что a1 и a2 одинаковы, если строка, которую они содержат, одинакова.

.. И ..

HashSet будет содержать только уникальные объекты.

0 голосов
/ 28 апреля 2010

Установить интерфейс не позволяет дублировать элементы. По этой причине вы получаете 3 в качестве вывода.

String s1= new String("abc");
  String s2= new String("abc");

Несмотря на то, что выше создает два объекта, но являются идентичными элементами.

0 голосов
/ 28 апреля 2010

Краткий ответ: потому что HashSet похож на математический набор , который по определению содержит только отдельные (уникальные) объекты. И, как уже говорили другие, два объекта, которые вы вставили, явно не оцениваются как отличающиеся друг от друга.

0 голосов
/ 28 апреля 2010

HashSet реализует интерфейс Set:

public interface Set<E> extends Collection<E>

С http://java.sun.com/j2se/1.5.0/docs/api/java/util/Set.html:

Коллекция, которая не содержит повторяющихся элементов. Более формально, множества не содержат пары элементов e1 и e2, таких как e1.equals (e2), и не более одного нулевого элемента. Как следует из его названия, этот интерфейс моделирует абстракцию математического набора.

Ответ:

Я считаю, что s1 и s2 будут найдены равными, и оба не могут содержаться в наборе. Невозможно определить, что объекты abc1 "равны". Таким образом, оба добавляются.

0 голосов
/ 28 апреля 2010

Поскольку вы добавляете три уникальных объекта - два объекта abc1 (вам нужно реализовать методы equals и hashCode для определения равенства) и строку (только один добавляется, поскольку он реализовал эти методы и данные сравниваемые в String объекты равны).

...