Рейтинговые книги
Читем онлайн Философия Java3 - Брюс Эккель

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 58 59 60 61 62 63 64 65 66 ... 132

Set имеет такой же интерфейс, что и Collection. В сущности, Set и является Collection, но обладает несколько иным поведением (кстати, идеальный пример использования наследования и полиморфизма: выражение разных концепций поведения). Пример использования HashSet с объектами Integer:

//• hoiding/SetOfInteger.java import java.util.*,

public class SetOfInteger {

public static void main(String[] args) { Random rand = new Random(47); Set<Integer> intset = new HashSet<Integer>(): for(int i = 0: i < 10000; i++)

i ntset.add(rand.nextInt(30)): System.out.printin(intset):

}

} /* Output:

[15, 8, 23, 16, 7, 22, 9, 21, 6, 1, 29, 14, 24, 4, 19, 26, 11, 18, 3, 12, 27, 17, 2, 13, 28, 20, 25, 10, 5, 0] *///:-

В множество включаются десять тысяч случайных чисел от 0 до 29; естественно, числа должны многократно повторяться. Но при этом мы видим, что в результатах каждое число присутствует только в одном экземпляре.

Также обратите внимание на непредсказуемый порядок следования чисел в выводе. Это объясняется тем, что HashSet использует хеширование для ускорения выборки. Порядок, поддерживаемый HashSet, отличается от порядка TreeSet или LinkedHashSet, поскольку каждая реализация упорядочивает элементы по-своему. Если вы хотите, чтобы результат был отсортирован, воспользуйтесь TreeSet вместо HashSet:

// hoiding/SortedSetOfInteger java import java util.*.

public class SortedSetOfInteger {

public static void main(String[] args) { Random rand = new Random(47), SortedSet<Integer> intset = new TreeSet<Integer>(), for(int i = 0. i < 10000; i++)

i ntset.add(rand.nextInt(30)); System.out println(intset);

}

} /* Output-

[0. 1. 2. 3. 4. 5. 6, 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29] *///.-

Одной из наиболее распространенных операций со множествами является проверка принадлежности методом contains(), но существуют и другие операции, которые напомнят вам диаграммы Венна из школьного курса:

// holding/SetOperations java import java.util.*.

import static net.mindview.util.Print.*;

public class SetOperations {

public static void main(String[] args) {

Set<String> setl = new HashSet<String>(); Col 1ecti ons.addAl1(setl.

"ABCDEFGHIJK L".splitC ")). setl.addCM");

printCH " + setl containsCH"));

printCN " + setl containsCN"));

Set<String> set2 = new HashSet<String>();

Col 1 ecti ons. addAl l(set2. "H I J К L" splitC "));

print("set2 in setl- " + setl containsAll(set2));

setl.removeCH");

print("setl. " + setl);

print("set2 in setl- " + setl.containsAll(set2)); setl removeAll(set2); printCset2 removed from setl: " + setl). Collections.addAll (setl. "X Y Z".splitC ")). printC'X Y Г added to setl. " + setl);

}

} /* Output H. true N- false

set2 in setl: true

setl: [D. К. С. B. L. G. I. M. A. F. J. E] set2 in setl- false

set2 removed from setl- [D. С. B. G. M. A. F. E] 'X Y Г added to setl: [Z. D. С. B. G. M. A. F. Y. X. E] *///.-

Имена методов говорят за себя. Информацию о других методах Set можно найти в документации JDK.

Карта

Возможность отображения одних объектов на другие (ассоциация) чрезвычайно полезна при решении широкого класса задач программирования. В качестве примера рассмотрим программу, анализирующую качество распределения класса Java Random. В идеале класс Random должен выдавать абсолютно равномерное распределение чисел, но чтобы убедиться в этом, необходимо сгенерировать большое количество случайных чисел и подсчитать их количество в разных интервалах. Множества упрощают эту задачу: ключом в данном случае является число, сгенерированное при помощи Random, а значением — количество его вхождений:

// holding/Statistics java

// Простой пример использования HashMap

import java util *.

public class Statistics {

public static void main(String[] args) { Random rand = new Random(47). Map<Integer,Integer> m =

new HashMap<Integer.Integer>(), for(int i = 0, i < 10000. i++) {

// Получение случайного числа от 0 до 20. int г = rand nextInt(20). Integer freq = m get(r). m.put(r. freq == null ? 1 freq +1).

}

System out println(m);

}

} /* Output

{15=497. 4=481. 19=464. 8=468. 11=531, 16=533, 18=478, 3=508, 7=471, 12=521, 17=509, 2=489, 13=506, 9=549, 6=519, 1=502, 14=477, 10=513, 5=503, 0=481} *///•-

В main() механизм автоматической упаковки преобразует случайно сгенери-рованое целое число в ссылку на Integer, которая может использоваться с HashMap (контейнеры не могут использоваться для хранения примитивов). Метод get() возвращает null, если элемент отсутствует в контейнере (то есть если число было сгенерировано впервые. В противном случае метод get() возвращает значение Integer, связанное с ключом, и последнее увеличивается на 1 (автоматическая упаковка снова упрощает вычисления, но в действительности при этом выполняются преобразования к Integer и обратно).

Следующий пример демонстрирует поиск объектов Pet по строковому описанию String. Он также показывает, как проверить присутствие некоторого ключа или значения в Map методами containsKey() и containsValue():

// holding/PetMap java import typeinfo.pets.*, import java util *;

import static net mindview util Print *;

public class PetMap {

public static void main(String[] args) {

Map<String,Pet> petMap = new HashMap<String.Pet>(). petMap put ("My Cat", new CatCMolly")). petMap put("My Dog", new Dog("Ginger")). petMap put ("My Hamster", new HamsterCBosco")). print(petMap).

Pet dog = petMap get("My Dog"), print(dog).

print(petMap containsKeyC'My Dog")), pri nt(petMap.contai nsValue(dog)).

}

} /* Output-

{My Cat=Cat Molly. My Hamster=Hamster Bosco. My Dog=Dog Ginger}

Dog Ginger

true

true

*///•-

Map, по аналогии с массивами и Collection, легко расширяются до нескольких измерений; достаточно создать Map со значениями типа Map (причем значениями этих Map могут быть другие контейнеры, и даже другие Map). Контейнеры легко комбинируются друг с другом, что позволяет быстро создавать сложные структуры данных. Например, если нам потребуется сохранить информацию о владельцах сразу нескольких домашних животных, для этого будет достаточно создать контейнер Map<Person,List<Pet»:

//. holding/MapOfList.java package holding; import typeinfo pets.*, import java.util.*.

import static net.mindview util Print *;

public class MapOfList {

public static Map<Person. List<? extends Pet»

petPeople = new HashMap<Person. Li st<? extends Pet»();

static {

petPeople put(new PersonC'Dawn").

Arrays asList(new Cymric("Molly").new Mutt("Spot"))). petPeople put(new Person("Kate").

Arrays asList(new CatC'Shackleton"),

new Cat("Elsie May"), new DogCMargrett"))); petPeople put(new Person("Marilyn"). Arrays asList(

new Pug("Louie aka Louis Snorkel stein Dupree"). new Cat("Stanford aka Stinky el Negro"), new CatC'Pinkola"))). petPeople put(new Person("Luke").

Arrays asList(new Rat("Fuzzy"). new Rat("Fizzy"))). petPeople put(new Person("Isaac").

Arrays asList(new RatCFreckly"))).

}

public static void main(String[] args) {

print ("People- " + petPeople keySetO). printOPets: " + petPeople valuesO); for(Person person . petPeople.keySet()) { print(person + " has-"); for(Pet pet • petPeople get(person))

printC " + pet); продолжение & }

}

} /* Output

People [Person Luke, Person Marilyn. Person Isaac, Person Dawn. Person Kate] Pets [[Rat Fuzzy. Rat Fizzy], [Pug Louie aka Louis Snorkel stein Dupree. Cat Stanford aka Stinky el Negro, Cat Pinkola]. [Rat Freckly]. [Cymric Molly. Mutt Spot], [Cat Shackleton, Cat Elsie May, Dog Margrett]] Person Luke has Rat Fuzzy Rat Fizzy Person Marilyn has

Pug Louie aka Louis Snorkel stein Dupree Cat Stanford aka Stinky el Negro Cat Pinkola Person Isaac has Rat Freckly Person Dawn has. Cymric Molly Mutt Spot Person Kate has-Cat Shackleton Cat Elsie May Dog Margrett */// ~

Map может вернуть множество (Set) своих ключей, коллекцию (Collection) значений или множество (Set) всех пар «ключ-значение». Метод keySet() создает множество всех ключей, которое затем используется в синтаксисе foreach для перебора Map.

Очередь

Очередь обычно представляет собой контейнер, работающий по принципу «первым вошел, первым вышел» (FIFO). Иначе говоря, элементы заносятся в очередь с одного «конца» и извлекаются с другого в порядке их поступления. Очереди часто применяются для реализации надежной передачи объектов между разными областями программы.

Класс LinkedList содержит методы, поддерживающие поведение очереди, и реализует интерфейс Queue, поэтому LinkedList может использоваться в качестве реализации Queue. В следующем примере LinkedList повышается восходящим преобразованием до Queue:

//: hoiding/QueueDemo.java

// Восходящее преобразование LinkedList в Queue

import java.util.*;

public class QueueDemo {

public static void printQCQueue queue) { while(queue.peek() != null)

System out print(queue.remove() + " "), System out printin(),

}

public static void main(String[] args) {

Queue<Integer> queue = new LinkedList<Integer>();

Random rand = new Random(47); for(int i = 0; i < 10; i++)

queue.offer(rand.nextlnt(i + 10)); printQ(queue);

Queue<Character> qc = new LinkedList<Character>(); for(char с ; "Brontosaurus".toCharArrayO)

qc.offer(c); printQ(qc);

}

} /* Output;

8 1 1 1 5 14 3 1 0 1

Brontosaurus

*///;-

Метод offer(), один из методов Queue, вставляет элемент в конец очереди, а если вставка невозможна — возвращает false. Методы реек() и element() возвращают начальный элемент без его удаления из очереди, но реек() для пустой очереди возвращает null, a element() выдает исключение NoSuchElementException. Методы poll() и remove() удаляют и возвращают начальный элемент очереди, но poll() для пустой очереди возвращает null, a remove() выдает NoSuchElementException.

Автоматическая упаковка преобразует результат int вызова nextlnt() в объект Integer, необходимый для queue, a char с — в объект Character, необходимый для qc. Интерфейс Queue сужает доступ к методам LinkedList так, что доступными остаются только соответствующие методы и у пользователя остается меньше возможностей для вызова методов LinkedList (конечно, queue можно преобразовать обратно в LinkedList, но это создает дополнительные затруднения).

PriorityQueue

Принцип FIFO описывает наиболее типичную организацию очереди. Именно организация очереди определяет, какой элемент будет следующим для заданного состояния очереди. Правило FIFO означает, что следующим элементом будет тот, который дольше всего находится в очереди.

В приоритетной очереди следующим элементом считается элемент, обладающий наивысшим приоритетом. Например, в аэропорту пассажира, самолет которого скоро улетит, могут пропустить без очереди. В системах обработки сообщений некоторые сообщения могут быть важнее других и должны обрабатываться как можно скорее, независимо от момента их поступления. Параметризованный класс PriorityQueue был добавлен в Java SE5 как механизм автоматической реализации этого поведения.

1 ... 58 59 60 61 62 63 64 65 66 ... 132
На этой странице вы можете бесплатно читать книгу Философия Java3 - Брюс Эккель бесплатно.
Похожие на Философия Java3 - Брюс Эккель книги

Оставить комментарий