Главная страница

Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция


Скачать 25.04 Mb.
НазваниеС. Н. Тригуб Перевод с английского и редакция
АнкорJava. Полное руководство. 8-е издание.pdf
Дата28.02.2017
Размер25.04 Mb.
Формат файлаpdf
Имя файлаJava. Полное руководство. 8-е издание.pdf
ТипДокументы
#3236
страница44 из 90
1   ...   40   41   42   43   44   45   46   47   ...   90
// Демонстрация применения Arrays,
import java.util.*;
class ArraysDemo {
public static void main(String a r g s []) {
// Распределить и инициировать массив
int a r r a y [] = new i n t [10];
for(int i = 0; i < 10; i
+
+)
array[i] = -3 * i;
// Отобразить, отсортировать и вновь отобразить массив.
System.out.print("Исходное содержимое ");
display(array);
Глава 17. Пакет java.util: инфраструктура Collections Fram ew ork
5 2 3
Arrays.sort(array);
System.o u t .p r i n t (Отсортированный массив ");
display(array);
// Наполнение и отображение массива r rays.fill(array,
2, 6, -1);
System.out.p r i n t (После fill(): ");
display(array);
// Сортировать и отобразить массив r После повторной сортировки ");
display(array);
// Бинарный поиск значения -9.
System.out.p r i n t (Значение -9 находится в позиции ");
int index =
Arrays.binarySearch(array,
-9);
System.out.println(index);
}
static void display(int a r r a y []) {
for(int i: array)
System.out.print(i + " ");
System.out.p r i Ниже показан вывод этой программы.
Исходное содержимое 0 -3 -6 -9 -12 -15
-18 -21 -24 -Отсортированный массив -27 -24 -21
-18
-15 -12 -9 -6
-3 О
После fil l (): -27 -24 -1 -1 -1 -1 -9 -6
-3 О
После повторной сортировки -27 -24
-9 -6 -3 -1 -1 -1 -1 О
Значение -9 находится в позиции Зачем нужны обобщенные коллекции
I
Как уже упоминалось вначале этой главы, в комплекте JDK 5 инфраструктура коллекций была перепроектирована для учета обобщений. Более того, инфраструктура коллекций — возможно, единственное наиболее важное применение обобщений в Java API. Причина этого в том, что обобщения обеспечивают безопасность типов инфраструктуры коллекций. Прежде чем двигаться дальше, стоит потратить некоторое время на детальное рассмотрение сущности этого усовершенствования. Это также объясняет, почему прежний код, написанный до появления обобщенных коллекций, должен быть модифицирован.
Давайте начнем с примера, который использует старый код, до введения обобщений. В следующей программе список строк сохраняется в объекте класса
A r r a y L i s t , а затем отображается содержимое списка Пример использования коллекций до введения обобщений
import java.util.*;
class OldStyle {
public static void main(String a r g s []) {
ArrayList list = new ArrayList();
// lines хранит строки, но могут быть сохранены объекты любого
// типа. В коде старого стиля нет возможности защитить тип
// сохраняемых в коллекции объектов
list.a d d (один
list.a d d (два

5 2 Часть И. Библиотека Java
list.a d d ("три");
list.add("четыре");
Iterator itr = list.iterator();
w h i l e (itr.h a s Next()) {
// Чтобы извлечь элемент, требуется явное приведение типов потому что коллекции хранят только Object.
String str = (String) itr.next(); // здесь необходимо явное
//приведение.
System.out.println(str + " имеет длину " + str.length() +
" символов.")?
}
}
}
До введения обобщенного синтаксиса все коллекции хранили ссылки на объекты класса
Obj e c t
. Это позволяло сохранять в них ссылки на объекты любого типа. Приведенная выше программа использует это свойство для хранения в списке объектов класса
S t r i n g , но также может сохранять ссылки любого другого типа.
К сожалению, тот факт, что коллекции старого вида сохраняют только объекты класса
O b j e c t , может легко приводить к ошибкам. В первую очередь, это требует, чтобы вы, а не компилятор, обеспечивали сохранение в конкретной коллекции только объектов правильных типов. Например, в предыдущем примере список однозначно предназначен для сохранения объектов класса
S t r i n g , нонет ничего, что действительно предотвратило бы добавление в коллекцию ссылок на объекты других типов. Так, например, компилятор не обнаружит ничего недопустимого в следующей строке кода Поскольку объект l i s t сохраняет ссылки на класс
O b j e c t , он может сохранить ссылку на класс
I n t e g e r
— точно также, как и ссылку на класс
S t r i n g . Но если вы предполагаете хранить в списке только строки, то предыдущий оператор повредит вашу коллекцию. К тому же компилятор не имеет никакой возможности узнать, что этот оператор неверен.
Вторая проблема со старыми (до введения обобщений) коллекциями в том, что когда вы получаете ссылку из коллекции, то должны вручную явно приводить эху ссылку к правильному типу. Вот почему предыдущая программа приводит ссылку, полученную от метода n e x t ( )
, к типу
S t r i n g . До введения обобщений коллекции просто сохраняли ссылки на класс
Obj e c t . Поэтому при извлечении объектов из коллекций необходимо было приведение типа.
Помимо неудобств, связанных с необходимостью приведения типов ссылок, этот недостаток информации о типе объектов приводит к довольно серьезными неожиданно легко порождаемым ошибкам. Поскольку класс
Obj e c t может быть приведен к любому объектному типу, всегда существовала возможность привести полученную из коллекции ссылку к неверному шипу Например, если к предыдущему примеру добавить следующий оператор, пример будет по-прежнему компилироваться без ошибок, но передавать исключение времени выполнения вовремя запуска программы i = (Integer) itr.next О Вспомните, что в предыдущем примере в объекте
list сохранялись только ссылки на экземпляры класса
S t r i n g . Поэтому при попытке приведения типа
S t r i n g к типу
I n t e g e r передается исключение неверного приведения типов. Так как это случится вовремя выполнения программы, подобная ошибка весьма серьезна.
Добавление обобщений кардинально повышает удобство использования и безопасность коллекций
Глава 17. Пакет java.util: инфраструктура Collections Fram ew ork
5 2 Гарантирует, что в коллекции будут сохранены только ссылки на объекты правильного типа. То есть коллекции всегда будут содержать ссылки известного типа.
• Исключает необходимость приведения типов ссылок, извлеченных из коллекции. Вместо этого ссылка, извлеченная из коллекции, будет автоматически приведена к правильному типу. Это предотвращает ошибки времени выполнения по причине неверного приведения и позволяет избежать целого ряда подобных ошибок.
Эти два усовершенствования стали возможны благодаря тому, что каждому классу коллекций может быть передан параметр, задающий тип коллекции. Например, класс
ArrayList теперь объявляется следующим образом Здесь Е — тип элемента, сохраняемого в коллекции. Таким образом, следующая строка объявляет объект класса
ArrayList для объектов класса
String.
ArrayList list = new Теперь в список могут быть добавлены только ссылки на объекты класса
String. Интерфейсы и
Listlterator теперь также стали обобщенными. Это означает, что параметр типа должен быть согласован с типом коллекции, для которой получен итератор. Более того, эта совместимость типов принудительно обеспечивается вовремя компиляции.
Следующая программа показывает современную, обобщенную, форму предыдущей программы Современная, обобщенная, версия
import java.util.*;
class NewStyle {
public static void main(String a r g s []) {
// Теперь list содержит ссылки типа String.
ArrayList list = new ArrayList();
list.a d d (один d d (два d d (три d d (четыре Отметим, что Iterator также обобщенный itr = list.iterator();
// Следующий оператор теперь вызовет ошибку времени компиляции Iterator itr = list.iterator(); // Ошибка
w h i l e (i t r .hasNext()) {
String str = itr.nextO; // приведение не требуется
// Теперь следующая строка породит ошибку компиляции, а не времени выполнения Integer i = itr.next(); // Это не откомпилируется
System.out.p r intln(str + " имеет длину " + str.length() +
" символов " )
Теперь список может содержать только ссылки на объекты класса
String. Более того, как видно из следующей строки, нет необходимости приводить тип объекта, возвращаемого методом next ()
, к типу
String.

5 2 Часть II. Библиотека Java
String str = itr.next(); приведение ненужно Приведение выполняется автоматически.
Поскольку существует поддержка базовых типов, прежний код, написанный до появления обобщенных коллекций, продолжает компилироваться и выполняться. Однако весь новый код должен быть обобщенным, а старый вы можете обновлять постепенно, при наличии свободного времени. Добавление обобщений в инфраструктуру коллекций — фундаментальное усовершенствование, которое следует использовать везде, где это возможно.
Унаследованные классы и интерфейсы
Как уже объяснялось вначале главы, ранние версии пакета j ava.
ut i
1 не включали в себя инфраструктуру коллекций. Вместо нее было определено несколько классов и интерфейсов, обеспечивающих специальные методы хранения объектов. Когда были добавлены коллекции (начиная с J2SE 1.2), некоторые исходные классы были перепроектированы для поддержки интерфейсов коллекций. То есть сейчас они, технически, являются частью инфраструктуры Collections Framework. Тем не менее, хотя новые коллекции дублируют функции устаревших классов, обычно выбудете использовать классы новых коллекций. Вообще, унаследованные классы поддерживаются потому, что существует код, использующий их.
Еще один момент ни один из современных классов коллекции, описанных в этой главе, не синхронизируется, а все устаревшие классы синхронизируются. Это различие может быть важным в некоторых ситуациях. Конечно, вы можете легко синхронизировать коллекции, используя один из алгоритмов, представленных интерфейсом Устаревшие классы, определенные в пакете j ava .util, показаны ниже.
Dictionary
Hashtable
Properties
Stack
Vector
Есть также один унаследованный интерфейс, называемый
Enumeration. Следующие разделы рассматривают этот интерфейс и каждый из унаследованных классов по очереди.
Интерфейс
E n u m e r a t i o Рассматриваемый интерфейс определяет методы, которыми вы можете перебирать (получая по одному зараз) элементы в коллекции объектов. Этот унаследованный интерфейс был замещен интерфейсом
Iterator. Хотя интерфейс
Enumeration и применяется, но считается устаревшим для нового кода. Однако он используется несколькими методами унаследованных классов (таких, как класс
Vector или
Properties), а также некоторыми другими классами API и широко используется существующим кодом приложений. Поскольку этот интерфейс все еще задействован, он был перепроектирован в обобщенном виде для комплекта
JDK 5. Интерфейс имеет следующее объявление Здесь Е определяет тип элементов, которые будут перебираться.
В интерфейсе определены следующие два метода Е nextElement()

Глава 17. Пакет java.util: инфраструктура Collections Fram ew ork
5 2 При реализации метод hasMoreElements
() должен возвращать значение true до тех пор, пока остаются элементы, подлежащие извлечению, и значение false
— когда все элементы уже перечислены. Метод next
Element
() возвращает следующий объект перечисления. То есть каждый вызов метода next
Element () получает следующий объект перечисления. По завершении перебора перечисления этот метод передает исключение
NoSuchElementExcept Класс

V e c t o Этот класс реализует динамический массив. Он подобен классу
ArrayList, но имеет два отличия класс
Vector синхронизирован и включает много устаревших методов, которые дублируют функции методов, определенных инфраструктурой
Collections Framework. С появлением коллекций класс
Vector был перепроектирован как расширение класса
Abs tract
List, ив него была добавлена реализация интерфейса
List. В версии 5 он был перепроектирован под применение обобщенного синтаксиса, ив нем появилась реализация интерфейса
Iterable. Это означает, что класс
Vector стал полностью совместимым с коллекциями и может выдавать свое содержимое в усовершенствованном цикле Класс
Vector объявлен следующим образом V e c t o r <Е>

Здесь Е определяет тип элементов, которые будут храниться.
Ниже перечислены конструкторы класса
Vector.
V e c t o r ()
Vecto r(i nt размер размер инкремент Первая форма создает вектор по умолчанию, имеющий начальный размер 10. Вторая форма создает вектор, начальная емкость которого равна размер Третья форма создает вектор с начальной емкостью размера инкремент указан в параметре инкремент .
Инкремент задает количество элементов, которые будут резервироваться при каждом увеличении размера вектора. Четвертая форма создает вектор, содержащий элементы коллекции с.
Все векторы начинаются с некоторой начальной емкости. Когда эта емкость заполнена, при следующей попытке сохранения объекта в векторе он автоматически увеличивает количество выделенного пространства по мере роста вектора. Это увеличение важно, поскольку резервирование памяти — дорогостоящая повремени операция. Общий объем дополнительного пространства памяти, выделенного при каждом резервировании, задается величиной инкремента, указанного при создании вектора. Если вы не указываете размер инкремента, размер вектора удваивается при каждом цикле резервирования памяти.
В классе
Vector определены следующие защищенные переменные члены capacitylncrement;

int elementCount;
O b j e c t [] Значение инкремента сохраняется в переменной capacitylncrement. Количество элементов, находящихся в данный момент в векторе, хранится в переменной elementCount. Массив, хранящий сам вектор, содержится в переменной В дополнение к методам коллекций, определенных в интерфейсе
List, класс
Vector определяет несколько унаследованных методов, которые перечислены в табл. 17.19.

5 2 Часть II. Библиотека Поскольку класс
Vector реализует интерфейс
List, вы можете использовать его также, как применяете экземпляр класса
ArrayList. Можно также манипулировать им, используя один из унаследованных методов. Например, после создания экземпляра класса
Vector вы можете добавлять элементы к нему с помощью метода addEle- ment ()
. Чтобы получить элемент, расположенный в определенной позиции, вызовите метод element
At
(). Чтобы получить первый элемент вектора, примените метода чтобы последний — метод lastElement
(). Индекс определенного элемента можно получить методом indexOf
() или lastlndexOf
(). Чтобы удалить элемент вектора, вызовите метод removeElement (
) или removeElementAt (Таблица 17.19. Унаследованные методы определенные в классе V e c t o r

Метод
Описание
void addElement(E элемент c a p a c i t y ()
Object c l o n e ()
boolean contains(Object элемент copyInto(Object
массив индекс e l e m e n t s ()

void ensureCapacity(int размер firstElement()
int indexOf(Object элемент indexOf(Object элемент начало (E элемент,
int индекс i s E m p t y O
E lastElement()
int lastlndexOf(Object элемент lastlndexOf(Object элемент int начало removeAllElements()
boolean
removeElement(Object элемент)
Объект, указанный в элемент, добавляется к вектору
Возвращает емкость вектора
Возвращает дубликат вызывающего объекта
Возвращает значение
true, если элемент содержится в векторе, и значение
false
— в противном случае
Элементы, содержащиеся в вызывающем векторе, копируются в массив массив
Возвращает элемент, расположенный в позиции индекс Возвращает перечисление элементов вектора
Устанавливает минимальную емкость вектора равной размер Возвращает первый элемент вектора
Возвращает индекс первого вхождения элемент. Если объект не найден в векторе, возвращает значение -Возвращает индекс первого вхождения элемент после начало.
Если объект не найден в векторе, возвращает значение -Добавляет элемент к вектору в позицию индекс
Возвращает значение
true, если вектор пусти значение
f
al
se
— в противном случае
Возвращает последний элемент вектора
Возвращает индекс последнего вхождения элемент.
Если объект не найден в векторе, возвращает значение -Возвращает индекс последнего вхождения элемент перед начало.
Если объект не найден в векторе, возвращает значение -Очищает вектор. После выполнения этого метода размер вектора равен нулю
Удаляет элемент из вектора. Если в векторе содержится более одного экземпляра данного элемента, то удаляется только первый из них. Возвращает значение
true, если элемент удален, и значение
false
— если объект не найден
Глава 17. Пакет java.util: инфраструктура Collections Fram ew ork
5 2 Окончание табл. 1719

.--r
void Удаляет из вектора элемент
,
расположенный в позиции индекс)
индекс
void setElementAt(E элемент int

индекс)
Устанавливается значение элемента в позиции индекс setSize(int

размер)
Устанавливается количество элементов вектора в размер. Если новый размер меньше старого, элементы теряются. Если же новый размер больше старого, добавляются пустые элементы Возвращает количество элементов, содержащихся в векторе to S t r i n g (Возвращает строковый эквивалент значения вектора Устанавливает емкость вектора равной количеству элементов, содержащихся в нем на данный момент
В следующей программе вектор используется для сохранения разных типов числовых объектов. В ней демонстрируется несколько унаследованных методов, определенных в классе
V e c t o r . Кроме того, в программе показана работа с интерфейсом
E n u m e r a t io n .
// Демонстрация различных операций с Vector,
import java.util.*;
1   ...   40   41   42   43   44   45   46   47   ...   90


написать администратору сайта