Философия Java


Функциональность Set - часть 2


Дублирующиеся значения добавляются в Set, но при распечатке вы увидите, что Set принял только один экземпляр каждого значения.

Когда вы запустите программу, вы заметите, что порядок, содержащийся в HashSet, отличается от TreeSet, так как каждый из них имеет различные способы сортировки элементов, так чтобы они могли быть найдены позднее. (TreeSet хранит их отсортированными, а HashSet использует функцию хеширования, которая предназначена специально для многократного поиска.) Когда создаете свои собственные типы, запомните, что для Set необходим способ обработки порядка сортировки, что означает, что вы должны реализовать интерфейс Comparable и определить метод compareTo( ). Вот пример:

//: c09:Set2.java

// Помещение своего типа в Set.

import java.util.*;

class MyType implements Comparable { private int i; public MyType(int n) { i = n; } public boolean equals(Object o) { return (o instanceof MyType) && (i == ((MyType)o).i); } public int hashCode() { return i; } public String toString() { return i + " "; } public int compareTo(Object o) { int i2 = ((MyType)o).i; return (i2 < i ? -1 : (i2 == i ? 0 : 1)); } }

public class Set2 { public static Set fill(Set a, int size) { for(int i = 0; i < size; i++) a.add(new MyType(i)); return a; } public static void test(Set a) { fill(a, 10); fill(a, 10); // Попытка создать дублирование

fill(a, 10); a.addAll(fill(new TreeSet(), 10)); System.out.println(a); } public static void main(String[] args) { test(new HashSet()); test(new TreeSet()); } } ///:~

Форма определения для equals( ) и hashCode( ) будет описана позднее в этой главе. Вы должны определить equals( ) в обоих классах, а hashCode( ) абсолютно необходима только если класс будет помещен в HashSet (что предпочтительнее, так как он должен быть выбран вами в первую очередь в качестве реализации Set). Однако, в качестве стиля программирования, вы должны всегда перегружать hashCode( ), когда вы перегружаете equals( ). Этот процесс будет позднее детализирован в этой главе.

Обратите внимание, что в методе compareTo( ) я не использую “простую и очевидную” форму return i-i2. Это общая ошибка программистов, это будет работать правильно, если i и i2 являются “беззнаковыми” целыми (если бы Java имел ключевое слово “unsigned”, но это не так). Это неправильно для отрицательных знаковых int в Java, который не достаточно велик, чтобы представить разность между двумя знаковыми int. Если i - это большое положительное целое, а j - это большое отрицательное целое, то при i-j будет переполнение и возвратится отрицательное значение, и это не будет работать.




Начало  Назад  Вперед