Успадкування та класи колекції

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Факультет "Інформатика та системи управління"
Методичні вказівки до лабораторної роботи
за курсом "Розподілені системи обробки інформації"
Успадкування та класи-колекції
Москва 2004

Зміст
Мета роботи .. 3
Завдання для домашньої підготовки. 3
Завдання до лабораторної роботи. 3
Завдання 1 Березня
Завдання 2 Квітень
Зміст звіту. 4
Контрольні питання. 4
Література. 6
Додаток 1. Специфікація класу Statistics. 7
Додаток 2. Робота з рядками. 9
Додаток 3. Класи - колекції. 20
Додаток 4. Робота з датами і часом. 41
Додаток 5. Файловий ввід / вивід. 43
Додаток 6. Обробка винятків. 48


Мета роботи

1. Навчитися працювати з колекціями і класами, що реалізують інтерфейс Collection.
2. Ознайомитись з основними класами пакету java.util.
3. Освоїти роботу з системним часом (Клас java.util.Date).
4. Навчитися працювати з файлами і потоками вводу / виводу.
5. Навчитися обробляти рядки (об'єкти класу String).
6. Застосувати отримані знання на практиці

Завдання для домашньої підготовки

1. Ознайомитися з матеріалом, наданим у додатках до даних методичних вказівок.
2. Вивчити приклади програм, що реалізують файловий ввід / вивід (див. Додаток 5).
3. Ознайомитися з текстом завдання до лабораторної роботи відповідно до варіанта і написати програму.

Завдання до лабораторної роботи

Завдання 1

2 варіанти:
1) Написати програму, яка зчитує текст з вхідного файлу, підраховує, скільки разів зустрівся кожен символ російського алфавіту, і виводить результат у вихідний файл, наприклад, у вигляді рядків "символ - число".
2) Написати програму, яка зчитує текст з вхідного файлу, формує безліч слів і виводить результат у вихідний файл. Однакові слова, які зустрілися в тексті, потрібно вивести в третій файл у вигляді рядків "слово - число".
Для обох варіантів:
o Класи - колекції, за допомогою яких буде виконана обробка тексту, студент вибирає самостійно.

Завдання 2

Рядки і файли [Л.2 на с.107-109]. Номер завдання відповідає порядковому номеру в журналі (за модулем 20).

Зміст звіту

Звіт повинен містити:
1. Постановку задачі, розв'язуваної налагодженої програмою.
2. Керівництво користувача налагодженої програми, що містить опис інтерфейсів всіх функцій програми.
3. Лістинг програми з необхідними коментарями.

Контрольні питання

1. Як змінити кодування символів ("KOI8_R", "Cp866", ...) в потоках вводу / виводу?
2. Як зробити програму нечутливою до регістру символів вхідного файлу?
3. Як змінити програму, щоб імена вхідних / вихідних файлів потрібно було б вводити з клавіатури або задавати в командному рядку.
4. Як потрібно змінити програму, щоб після оголошення методу public static void main (String [] args) не потрібно було б записувати throws IOException.
5. Як відомо, час у додатки Java записується у вигляді цілочисельних значень типу long, виражених в мілісекундах і відлік яких ведеться з півночі (00:00:00 GMT) 1 січня 1970 року. На скільки років вистачить розміру (8байт) значення типу long для відліку мілісекунд?
6. Як можна змінити програму, щоб підрахувати час обробки файлів без використання класу Date, ввівши одну додаткову зміну.
7. Як порівняти два рядки.
8. Як вибрати i-ий символ рядка.


Література

1. Арнолд К., Гослінг Дж., Холмс Д. Мова програмування Java: Пер. з англ. - М.: Видавничий дім «Вільямс», 2001 р. - 624 с., Іл.
2. Павловська Т.О., Щупак Ю.А. С / С + +. Структурне програмування: Практикум. -СПб.: Пітер, 2002. -240с.
Додаткова
1. Офіційний сайт Java - http://java.sun.com/ (є розділ російською мовою з підручником).
2. Java ™ 2 SDK, Standard Edition Documentation - http://java.sun.com/products/jdk/1.5/index.html.
3. Джеймс Гослінг, Білл Джой, Гай Стіл. Специфікація мови Java (The Java Language Specification - http://www.javasoft.com/docs/books/jls/). Переклад на російську мову - http://www.uni-vologda.ac.ru/java/jls/index.html
4. Офіційний сайт проекту Eclipse - http://www.eclipse.org/.
А також
5. Дмитро Рамодін. Починаємо програмувати на мові Java.
6. Микола Смирнов. Java 2: Навчальний посібник.
7. Картузов А. В. Програмування на мові Java.
8. Вязовік Н.А. Програмування на Java.

Додаток 1. Специфікація класу Statistics.
import java.io. *; / / підключення пакету з класами вводу / виводу
import java.util .*; / / підключення пакету з класами колекцій і часу
public class Statistics {
public static void main (String [] args) throws IOException {
BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream ("d: \ \ input.txt"));
/ / Вхідний потік - з файлу d: \ input.txt
BufferedWriter bw = new BufferedWriter (new OutputStreamWriter (new FileOutputStream ("d: \ utput.txt"));
/ / Вихідний потік - в файл d: utput.txt
/ / Ініціалізація екземпляра класу, що реалізує інтерфейс колекцій
int c = 0;
Date before = new Date (); / / зафіксували час перед обробкою
while ((c = br.read ())! = -1) {/ / поки не досягнуть кінець файлу d: \ input.txt
/ / Обробка
/ *
наприклад, якщо раніше визначена рядок String s = "";
то можна записати s + = (char) c;
Тоді весь вміст файлу d: \ input.txt буде записано в рядок s
* /
}
br.close (); / / закриваємо вхідний потік після прочитання і попередньої обробки
for (/ * цикл * /) {
/ / Обробка і запис у вихідний потік
bw.write (/ * слово * / + "" + / * число * / + "\ r \ n");
}
bw.close (); / / закриваємо вихідний потік після запису файлу
Date after = new Date (); / / фіксуємо час після обробки
System.out.println ("Обробка продовжувалася" + (after.getTime ()-before.getTime ())+" мілісекунд ");
/ / Виводимо на консоль час обробки в мілісекундах
} / / Кінець public static void main (String [] args)
} / / Кінець класу Statistics

Додаток 2. Робота з рядками

Дуже велике місце в обробці інформації займає робота з текстами. Як і багато іншого, текстові рядки в мові Java є об'єктами. Вони видаються екземплярами класу String або класу StringBuffer.
Навіщо в мову введено два класи для зберігання рядків? У об'єктах класу String зберігаються рядки-константи незмінною довжини і змісту. Це значно прискорює обробку рядків і дозволяє економити пам'ять, розділяючи рядок між об'єктами, які використовують її. Довжину рядків, що зберігаються в об'єктах класу StringBuffer, можна міняти, вставляючи і додаючи рядки і символи, видаляючи підрядки або зчіплюючи кілька рядків в один рядок.
Нагадаємо, що символи в рядках зберігаються в кодуванні Unicode, в якій кожен символ займає два байти. Тип кожного символу char.

Клас String

Перед роботою з рядком її слід створити. Це можна зробити різними способами.
Найпростіший спосіб створити рядок - це організувати посилання типу String на рядок-константу:
String si = "Це рядок.";
Якщо константа довга, можна записати її в кількох рядках текстового редактора, пов'язуючи їх операцією зчеплення:
String s2 = "Це довга рядок," +
"Записана у двох рядках вихідного тексту";
Не забувайте різницю між порожній рядком String s = "", яка не містить жодного символу, і порожній посиланням String s = null, не вказує ні на який рядок і не є об'єктом.
Найправильніший спосіб створити об'єкт з точки зору ООП - це викликати його конструктор в операції new. Клас String надає дев'ять конструкторів:
· String () - створюється об'єкт з порожнім рядком;
· String (String str) - з одного об'єкта створюється інший, тому цей конструктор використовується рідко;
· String (StringBuffer str) - перетворена копія об'єкта класу StringBuffer;
· String (byte [] byteArray) - об'єкт створюється з масиву байтів byteArray;
· String (char [] charArray) - об'єкт створюється з масиву charArray символів Unicode;
· String (byte [] byteArray, int offset, int count) - об'єкт створюється з частини масиву байтів byteArray, що починається з індексу offset і містить count байтів;
· String (char [] charArray, int offset, int count) - те ж, але масив складається з символів Unicode;
· String (byte [] byteArray, String encoding) - символи, записані в масиві байтів, задаються в Unicode-рядку, з урахуванням кодування encoding;
· String (byte [] byteArray, int offset, int count, String encoding) - те ж саме, але тільки для частини масиву.
При неправильному завданні індексів offset, count або кодування encoding виникає виняткова ситуація.
У кирилиці є, щонайменше, чотири кодування:
· У MS-DOS застосовується кодування ср866.
· У UNIX зазвичай застосовується кодування KOI8-R.
· На комп'ютерах Apple Macintosh використовується кодування MacCyrillic.
· Є ще й міжнародна кодування кирилиці ISO8859-5;
Якщо вихідний кириличний ASCII-текст був в одній з цих кодувань, а місцева кодування СР1251, то Unicode-символи рядка Java не будуть відповідати кирилиці.
У цих випадках використовуються останні два конструктора, в яких параметром encoding вказується, яку кодову таблицю використовувати конструктору при створенні рядка.
Ще один спосіб створити рядок - це використовувати два статичних методу
copyValueOf (char [] charArray) і copyValueOf (char [] charArray, int offset, int length).
Вони створюють рядок по заданому масиву символів і повертають її в якості результату своєї роботи. Наприклад, після виконання наступного фрагменту програми
char [] з = ('З', 'і', 'м', 'в', 'про 1,' л ',' ь ',' н ',' и ',' й '};
String s1 = String.copyValueOf (с);
String s2 = String.copyValueOf (з, 3, 7);
отримаємо в об'єкті s1 рядок "Символьний", а в об'єкті s2 - рядок "вільний".

Зчеплення рядків

З рядками можна проводити операцію зчеплення рядків, що позначається знаком плюс +. Ця операція створює новий рядок, просто складену з зістикованих першої та другої рядків. Її можна застосовувати і до констант, і до змінних. Наприклад:
String attention = "Увага:";
String s = attention + "невідомий символ";
Друга операція - привласнення + = - застосовується до змінних в лівій частині:
attention + = s;
Оскільки операція + переобтяжена з складання чисел на зчеплення рядків, встає питання про пріоритет цих операцій. У зчеплення рядків пріоритет вище, ніж у складання, тому, записавши "2" + 2 + 2, отримаємо рядок "222". Але, записавши 2 + 2 + "2", отримаємо рядок "42", оскільки дії виконуються зліва направо. Якщо ж запишемо "2" + (2 + 2), то отримаємо "24".

Маніпуляції рядками

У класі String є безліч методів для роботи з рядками.
Як дізнатися довжину рядка
Для того щоб дізнатися довжину рядка, тобто кількість символів в ній, треба звернутися до методу length ():
String s = "Write once, run anywhere.";
int len ​​= s.length {);
або ще простіше
int len ​​= "Write once, run anywhere.". length ();
оскільки рядок-константа - повноцінний об'єкт класу String. Зауважте, що рядок - це не масив, у неї немає поля length.
Як вибрати символи з рядка
Вибрати символ з індексом ind (індекс першого символу дорівнює нулю) можна методом charAt (int ind) Якщо індекс ind негативний або не менше ніж довжина рядка, виникає виняткова ситуація.
Усі символи рядка у вигляді масиву символів можна отримати методом toCharArray (), що повертає масив символів.
Якщо ж треба включити в масив символів dst, починаючи з індексу ind масиву підрядок від індексу begin включно до індексу end виключно, то використовуйте метод getChars (int begin, int end, char [] dst, int ind) типу void.
У масив буде записано end - begin символів, які займуть елементи масиву, починаючи з індексу ind до індексу ind + (end - begin) - 1.
Якщо треба отримати масив байтів, що містить всі символи рядка в байтовой кодуванні ASCII, то використовуйте метод getBytes ().
Цей метод при перекладі символів з Unicode в ASCII використовує локальну кодову таблицю.
Якщо ж треба отримати масив байтів не в локальній кодуванні, а в якійсь іншій, використовуйте метод getBytes (String encoding).
Як вибрати підрядок
Метод substring (int begin, int end) виділяє підрядок від символу з індексом begin включно до символу з індексом end виключно. Довжина підрядка буде дорівнює end - begin.
Метод substring (int begin) виділяє підрядок від індексу begin включно до кінця рядка.
Якщо індекси негативні, індекс end більше довжини рядка або begin більше ніж end, то виникає виняткова ситуація.
Наприклад, після виконання
String s = "Write onсe, run anywhere.";
String sub1 = s.substring (6, 10);
String sub2 = s.substring (16);
отримаємо в рядку sub1 значення "once", а в sub2 - значення "anywhere".
Як порівняти рядки
Операція порівняння == зіставляє тільки посилання на рядки. Вона з'ясовує, чи вказують посилання на одну і ту ж рядок. Наприклад, для рядків
String s1 = "Якась рядок";
String s2 = "Другая-рядок";
порівняння s1 == s2 дає в результаті false.
Значення true вийде, тільки якщо обидва посилання вказують на одну й ту ж рядок, наприклад, після присвоєння si = s2.
Цікаво, що якщо ми визначимо s2 так:
String s2 == "Якась рядок";
то порівняння s1 == s2 дасть у результаті true, тому що компілятор створить тільки один екземпляр константи "Якась рядок" і направить на нього всі посилання.
Для порівняння вмісту рядків є кілька методів.
Логічний метод equals (Object obj), перевизначення з класу Оbject, повертає true, якщо аргумент obj не дорівнює null, є об'єктом класу String, і рядок, що міститься в ньому, повністю ідентична цьому рядку аж до збігу регістра букв. В інших випадках повертається значення false.
Логічний метод equalsIgnoreCase (Object obj) працює так само, але однакові букви, записані в різних регістрах, вважаються співпадаючими.
Метод compareTo (string str) повертає ціле число типу int, обчислена за такими правилами:
1. Порівнюються символи цього рядка this і рядки str з однаковим індексом, поки не зустрінуться різні символи з індексом, допустимо k, або поки одна з рядків не закінчиться.
2. У першому випадку повертається значення this.charAt (k) - str.charAt (k), тобто різниця кодувань Unicode перший незбіжних символів.
3. У другому випадку повертається значення this.length () - str.length (), тобто різниця довжин рядків.
4. Якщо рядки співпадають, повертається 0.
Якщо значення str одно null, виникає виняткова ситуація.
Нуль повертається в тій же ситуації, в якій метод equals () повертає true.
Метод compareToignoreCase (string str) виробляє порівняння без урахування регістру букв, точніше кажучи, виконується метод
this.toUpperCase (). toLowerCase (). compareTo (
str.toUpperCase (). toLowerCase ());
Ще один метод-compareTo (Object obj) створює виняткову ситуацію, якщо obj не є рядком. В іншому він працює як метод compareTo (String str).
Ці методи не враховують алфавітне розташування символів в локальній кодуванні.
Російські літери розташовані в Unicode за алфавітом, за винятком однієї літери. Заголовна літера Е розташована перед усіма кириличними літерами, її код '\ u040l', а мала літера е - після всіх російських букв, її код '\ u0451'.
Кодування російських букв:
'А' ~ 1040 ~ \ u410
'Я' ~ 1071 ~ \ u42F
'А' ~ 1072 ~ \ u430
'Я' ~ 1103 ~ \ u44F
Як знайти символ в рядку
Пошук завжди ведеться з урахуванням регістру букв.
Перша поява символу ch в даному рядку this можна відстежити методом indexOf (int ch), що повертає індекс цього символу в рядку або -1, якщо символу ch в рядку this немає.
Наприклад, "Молоко", indexOf ('про') видасть в результаті 1.
Друге і наступні появи символу ch в даному рядку this можна відстежити методом indexOf (int ch, int ind).
Цей метод починає пошук символу ch з індексу ind. Якщо ind <0, то пошук йде з початку рядка, якщо ind більше довжини рядка, то символ не шукається, тобто повертається -1.
Остання поява символу ch в даному рядку this відстежує метод lastIndexof (int ch). Він переглядає рядок у зворотному порядку. Якщо символ ch не знайдений, возвращается.-1.
Передостаннє і попередні появи символу ch в даному рядку this можна відстежити методом lastIndexof (int ch, int ind), який переглядає рядок у зворотному порядку, починаючи з індексу ind.
Якщо ind більше довжини рядка, то пошук йде від кінця рядка, якщо ind <0, то повертається -1.
Як знайти підрядок
Пошук завжди ведеться з урахуванням регістру букв.
Перше входження підрядка sub в даний рядок this відшукує метод indexof (String sub). Він повертає індекс першого символу першого входження підрядка sub в рядок або -1, якщо підрядок sub не входить в рядок this.
Якщо ви хочете почати пошук не з початку рядка, а з якогось індексу ind, використовуйте метод indexOf (String sub, int ind). якщо ind <0, то пошук йде з початку рядка, якщо ind більше. довжини рядка, то символ не шукається, тобто повертається -1.
Остання входження підрядка sub в даний рядок this можна відшукати методом lastindexof (string sub), що повертає індекс першого символу останнього входження підрядка sub в рядок this або (-1), якщо підрядок sub не входить в рядок this.
Остання входження підрядка sub не у весь рядок this, а тільки в її початок до індексу ind можна відшукати методом lastIndexof (String stf, int ind). Якщо ind більше довжини рядка, то пошук йде від кінця рядка, якщо ind <0, то повертається -1.
Перераховані вище методи створюють виняткову ситуацію, якщо
sub == null.
Якщо ви хочете здійснити пошук, не враховує регістр букв, змініть попередньо реєстр усіх символів рядка.
Як змінити регістр символів
Метод toLowerCase () повертає новий рядок, в якій всі букви переведені в нижній регістр, тобто зроблені малими.
Метод toUpperCase () повертає новий рядок, в якій всі букви переведені у верхній регістр, тобто зроблені великими.
При цьому використовується локальна кодова таблиця за замовчуванням. Якщо потрібна інша локаль, то застосовуються методи toLowerCase (Locale loc) і toUpperCase (Locale loc).
Як замінити окремий символ
Метод replace (int old, int new) повертає новий рядок, в якій всі входження символу old замінені символом new. Якщо символу old в рядку немає, то повертається посилання на вихідну рядок.
Наприклад, після виконання "Рука в руку суне хліб", replace ('у', 'е') отримаємо рядок "Річка в річці сіє хліб".
Регістр букв при заміні враховується.
Як прибрати пропуски на початку і кінці рядка
Метод trim () повертає новий рядок, в якої вилучені початкові і кінцеві символи з кодами, що не перевищують '\ u0020'.
Як перетворити дані іншого типу в рядок
У мові Java прийнято угоду - кожен клас відповідає за перетворення інших типів у тип цього класу і має містити потрібні для цього методи.
Клас String містить вісім статичних методів valueof (type elem) перетворення в рядок примітивних типів boolean, char, int, long, float, double, масиву char [], і просто об'єкта типу Object.
Дев'ятий метод valueof (char [] ch, int offset, int len) перетворює в рядок подмассів масиву ch, що починається з індексу offset і має len елементів.
Крім того, в кожному класі є метод toString (), перевизначення або просто успадкований від класу Object. Він перетворює об'єкти класу в рядок. Фактично, метод valueOf () викликає метод toString () відповідного класу. Тому результат перетворення залежить від того, як реалізований метод toString ().
Ще один простий спосіб - зчепити значення elem будь-якого типу з порожнім рядком: "" + elem. При цьому неявно викликається метод elem.toString ().

Синтаксичний розбір рядка

Завдання розбору введеного тексту - вічна завдання програмування, поряд з сортуванням і пошуком.
У пакет java.util входить простий клас StringTokenizer, полегшує розбір рядків.
Клас StringTokenizer
Клас StringTokenizer з пакету java.util невеликий, у ньому три конструктори і шість методів.
Перший конструктор StringTokenizer (String str) створює об'єкт, готовий розбити рядок str на слова, розділені пробілами, символами табуляцій '\ t', перекладу рядка '\ n' і повернення каретки '\ r'. Роздільники не включаються в число слів.
Другий конструктор StringTokenizer (String str, String delimeters) задає роздільники другим параметром delimeters, наприклад:
StringTokenizer ("Стратити, не можна: прогалин-ні", "\ t \ n \ r ,:-");
Тут перший роздільник - пробіл. Потім йдуть символ табуляції, символ переведення рядка, символ повернення каретки, кома, двокрапка, дефіс. Порядок розташування роздільників у рядку delimeters не має значення. Роздільники не включаються в число слів.
Третій конструктор дозволяє включити роздільники в число слів:
StringTokenizer (String str, String delimeters, boolean flag);
У розборі рядка на слова активно беруть участь наступні методи:
o метод nextToken () повертає у вигляді рядка наступне слово.
o метод hasMoreTokens () повертає true, якщо в рядку ще є слова, і false, якщо слів більше немає.
o метод countTokens () повертає число залишилися слів.
o метод nextToken (string newDelimeters) дозволяє "на ходу" міняти роздільники. Наступне слово буде виділено по новим розділювачам newDelimeters; нові роздільники діють далі замість старих роздільників, визначених у конструкторі або попередньому методі nextToken ().
o методи nextElement () і hasMoreElements () реалізують інтерфейс Enumeration. Вони просто звертаються до методів nextToken () і hasMoreTokens ().
Приклад. Розбиття рядка на слова:
String s = "Рядок, що ми хочемо розібрати на слова";
StringTokenizer st = new StringTokenizer (s, "\ t \ n \ r ,.");
while (st.hasMoreTokens ()) {
/ / Отримуємо слово і що-небудь робимо з ним, наприклад,
/ / Просто виводимо на екран
System.out.println (st.nextToken ());
}
Отримані слова зазвичай заносяться в якій-небудь клас-колекцію: Vector, Stack або інший, найбільш підходящий для подальшої обробки тексту контейнер. Класи-колекції ми розглянуті далі.

Додаток 3. Класи - колекції

При вирішенні завдань, в яких кількість елементів заздалегідь невідомо, елементи треба часто видаляти і додавати використовуються колекції.
У мові Java з найперших версій є клас Vector, призначений для зберігання змінного числа елементів самого загального типу Object.

Клас Vector

У класі Vector з пакету java.util зберігаються елементи типу Object, а значить, будь-якого типу. Кількість елементів може бути будь-яким і наперед не визначатися. Елементи отримують індекси 0, 1, 2, .... До кожного елементу вектора можна звернутися за індексом, як і до елементу масиву.
Крім кількості елементів, званого розміром (size) вектора, є ще розмір буфера - ємність (capacity) вектора. Зазвичай ємність збігається з розміром вектора, але можна її збільшити методом ensureCapacity (int minCapacity) або зрівняти з розміром вектора методом trimToSize ().
Як створити вектор
У класі чотири конструктора:
Vector () - створює порожній об'єкт нульової довжини;
Vector (int capacity) - створює порожній об'єкт зазначеної ємності capacity;
Vector (int capacity, int increment) - створює порожній об'єкт зазначеної ємності capacity і задає число increment, на яку збільшується ємність при необхідності;
vector (Collection с) - вектор створюється за вказаною колекції. Якщо capacity негативно, створюється виняткова ситуація. Після створення вектора його можна заповнювати елементами.
Як додати елемент у вектор
Метод add (Object element) дозволяє додати елемент в кінець вектора.
Методом add (int index, Object element) можна вставити елемент у вказане місце index. Елемент, що знаходився на цьому місці, і всі наступні елементи зсуваються, їх індекси збільшуються на одиницю.
Метод addAll (Collection coll) дозволяє додати в кінець вектора всі елементи колекції coll.
Методом addAll (int index, Collection coll) можливо вставити в позицію index всі елементи колекції coll.
Як замінити елемент
Метод set (int index, Object element) замінює елемент, що стояв у векторі в позиції index, на елемент element.
Як дізнатися розмір вектора
Кількість елементів у векторі завжди можна дізнатися методом size (). Метод capacity () повертає ємкість вектора.
Логічний метод isEmpty () повертає true, якщо у векторі немає жодного елемента.
Як звернутися до елементу вектора
Звернутися до першого елемента вектора можна методом firstElement (), до останнього - методом lastElement (), до будь-якого елементу - методом get (int index).
Ці методи повертають об'єкт класу Object. Перед використанням його слід привести до потрібного типу.
Отримати всі елементи вектора у вигляді масиву типу Object [] можна методами toArray) і toArray (Object [] а). Другий метод заносить всі елементи вектора в масив а, якщо в ньому достатньо місця.
Як дізнатися, чи є елемент у векторі
Логічний метод contains (Object element) повертає true, якщо елемент element знаходиться у векторі.
Логічний метод containsAll (Collection с) повертає true, якщо вектор містить всі елементи зазначеної колекції.
Як дізнатися індекс елементу
Чотири методи дозволяють відшукати позицію вказаного елемента element:
indexOf (Object element) - повертає індекс першої появи елемента у векторі;
indexOf (Object element, int begin) - веде пошук, починаючи з індексу begin включно;
lastindexOf (Object element) - повертає індекс останньої появи елемента у векторі;
lastindexOf (Object element, int start) - веде пошук від індексу start включно до початку вектора.
Якщо елемент не знайдений, повертається -1.
Як видалити елементи
Логічний метод remove (Object element) видаляє з вектора перше входження зазначеного елемента element. Метод повертає true, якщо елемент знайдений і видалення вироблено.
Метод remove (int index) видаляє елемент з позиції index і повертає його в якості свого результату типу Object.
Видалити діапазон елементів можна методом removeRange (int begin, int end), не повертає результату. Видаляються елементи від позиції begin включно до позиції end виключно.
Видалити з цього вектора всі елементи колекції coll можливо логічним Методом removeAll (Collection coll).
Видалити останні елементи можна, просто урізавши вектор методом
setSizefint newSize).
Видалити всі елементи, крім містяться в цій колекцію coll, дозволяє логічний метод retainAll (Collection coll).
Видалити всі елементи вектора можна методом clear () або обнуливши розмір вектора методом setSize (O).
Даний лістинг доповнює приклад, записаний у додатку 2, обробляючи виділені з рядка слова за допомогою вектора.
Робота з вектором
Vector v = new Vector ();
String s = "Рядок, що ми хочемо розібрати на слова.";
StringTokenizer st = new StringTokenizer (s, "\ t \ n \ r ,.");
while (st.hasMoreTokens ()) {
/ / Отримуємо слово і заносимо у вектор
v.add (st.nextToken ()); / / Додаємо в кінець вектора
}
System.out.println (v.firstElement ()); / / Перший елемент
System.out.println (v.lastElement ()); / / Останній елемент
v.setSize (4); / / Зменшуємо число елементів
v.add ("зібрати."); / / Додаємо в кінець
/ / Укороченого вектора
v.set (3, "знову"); / / Ставимо в позицію 3
for (int i = 0; i <v.sizeO; i + +) / / Перебираємо весь вектор
System.out.print (v.get (i) + "");
System.out.println ();
Клас Vector є прикладом того, як можна об'єкти класу Object, a значить, будь-які об'єкти, об'єднати в колекцію. Цей тип колекції впорядковує і навіть нумерує елементи. У векторі є перший елемент, є останній елемент. До кожного елементу звертаються безпосередньо за індексом. При додаванні і видаленні елементів залишилися елементи автоматично перенумеровуються.
Другий приклад колекції - клас Stack - розширює скарбі Vector.

Клас Stack

Клас Stack з пакету java.util. об'єднує елементи в стек.
Стек (Stack) реалізує порядок роботи з елементами подібно магазину гвинтівки-першим вистрілить патрон, покладений в магазин останнім, - або подібно залізничному тупику - першим з глухого кута вийде вагон, загнаний туди останнім. Такий порядок обробки називається LIFO (Last In - First Out).
Перед роботою створюється порожній стек конструктором Stack ().
Потім на стек кладуться і знімаються елементи, причому доступний тільки "верхній" елемент, той, що покладено на стек останнім.
Додатково до методів класу vector клас Stack містить п'ять методів, що дозволяють працювати з колекцією як зі стеком:
push (Object item)-поміщає елемент item в стек;
pop () - витягує верхній елемент з стека;
peek () - читає верхній елемент, не витягуючи його з стека;
empty () - перевіряє, чи не порожній чи стек;
search (Object item) - знаходить позицію елемента item в стеку. Верхній елемент має позицію 1, під ним елемент 2 і т. д. Якщо елемент не знайдений, повертається - 1.
Ще один приклад колекції зовсім іншого роду - таблиці - надає клас Hashtable.

Клас Hashtable

Клас Hashtable розширює абстрактний клас Dictionary. У об'єктах цього класу зберігаються пари "ключ - значення".
З таких пар "Прізвище І. О. - номер" складається, наприклад, телефонний довідник.
Кожен об'єкт класу Hashtable крім розміру (size) - кількості пар, має ще дві характеристики: ємність (capacity) - розмір буфера, і показник завантаженості (load factor) - відсоток заповнювання буфера, після досягнення якого збільшується його розмір.
Як створити таблицю
Для створення об'єктів клас Hashtable надає чотири конструктора:
Hashtable () - створює порожній об'єкт з початковою ємністю в 101 елемент і показником завантаженості 0,75;
Hashtable (int capacity) - створює порожній об'єкт з початковою ємкістю capacity і показником завантаженості 0,75;
Hashtable (int capacity, float loadFactor) - створює порожній Об'єкт з початковою ємністю capacity і показником завантаженості loadFactor;
Hashtable (Map f) - створює об'єкт класу Hashtable, що містить всі елементи відображення f, з ємністю, що дорівнює подвоєному числу елементів відображення f, але не менше 11, і показником завантаженості 0,75.
Як заповнити таблицю
Для заповнення об'єкта класу Hashtable використовуються два методи:
Object put (Object key, Object value) - додає пару "key - value", якщо ключа key не було в таблиці, і змінює значення value ключа key, якщо він вже є в таблиці. Повертає старе значення ключа або null, якщо його не було. Якщо хоча б один параметр дорівнює null, виникає виняткова ситуація;
void putAll (Map f) - додає всі елементи відображення f. У об'єктах-ключах key повинні бути реалізовані методи hashCode () і equals ().
Як отримати значення по ключу
Метод get (Object key) повертає значення елемента з ключем key у вигляді об'єкту класу Object. Для подальшої роботи його слід перетворити до конкретного типу.
Як дізнатися наявність ключа або значення
Логічний метод containsKey (Object key) повертає true, якщо в таблиці є ключ key.
Логічний метод containsvalue (Object value) або старий метод contains (Object value) повертають true, якщо в таблиці є ключі із значенням value.
Логічний метод isEmpty () повертає true, якщо в таблиці немає елементів.
Як отримати всі елементи таблиці
Метод values ​​() представляє всі значення value таблиці у вигляді інтерфейсу Collection. Всі модифікації в об'єкті collection змінюють таблицю, і навпаки.
Метод keyset () надає всі ключі key таблиці у вигляді інтерфейсу set. Всі зміни в об'єкті set коректують таблицю, і навпаки.
Метод entrySet () представляє всі пари "key - value" таблиці у вигляді інтерфейсу Set. Всі модифікації в об'єкті Set змінюють таблицю, і навпаки.
Метод toString () повертає рядок, що містить всі пари.
Як видалити елементи
Метод remove (Object key) видаляє пару з ключем key, повертаючи значення цього ключа, якщо воно є, і null, якщо пара з ключем key не знайдена.
Метод clear () видаляє всі елементи, очищаючи таблицю.
Приклад програми «Телефонний довідник».
import java.util .*;
class PhoneBook {
public static void main (String [] args) {
Hashtable yp = new Hashtable ();
String name = null;
yp.put ("John", "123-45-67");
yp.put ("Lemon", "567-34-12");
yp.put ("Bill", "342-65-87");
yp.put ("Gates", "423-83-49");
yp.put ("Batman", "532-25-08");
try {
name = args [0];
}
catch (Exception e) {
System.out.println ("Usage: Java PhoneBook Name");
}
return;
}
if (yp.containsKey (name))
System.out.println (name + "'s phone =" + yp.get (name));
else
System.out.println ("Sorry, no such name");
)
}

Клас Properties

Клас Properties розширює клас Hashtable. Він призначений в основному для введення і виведення пар властивостей системи та їх значень. Пари зберігаються у вигляді рядків типу String. У класі Properties два конструктора:
Properties () - створює порожній об'єкт;
Properties (Properties default) - створює об'єкт із заданими парами властивостей default.
Крім успадкованих від класу Hashtable методів у класі Properties є ще такі методи.
Два методи, які повертають значення ключа-рядки у вигляді рядка:
• String getProperty (String key) - повертає значення по ключу key;
• String getProperty (String.key, String defaultValue) - повертає значення по ключу key; якщо такого ключа немає, повертається defaultValue.
Метод setProperty (String key, String value) додає нову пару, якщо ключа key немає, і змінює значення, якщо ключ key є.
Метод load (Inputstream in) завантажує властивості з вхідного потоку in.
Методи list (PrintStream out) І list (PrintWriter out) виводять властивості у вихідний потік out.
Метод store (OutputStream out, String header) виводить властивості у вихідний потік out із заголовком header.

Малюнок. Ієрархія класів та інтерфейсів-колекцій.
Приклади класів Vector, Stack, Hashtable, Properties показують зручність класів-колекцій. Тому в Java 2 розроблена ціла ієрархія колекцій. Вона показана на малюнку. Праворуч записані імена інтерфейсів. Стрілки вказують класи, що реалізують ці інтерфейси. Усі колекції розбиті на три групи, описані в інтерфейсах List, Set і Map.
Прикладом реалізації інтерфейсу List може служити клас Vector, прикладом реалізації інтерфейсу березня - клас Hashtable.
Колекції List і Set мають багато спільного, тому їх загальні методи об'єднані і винесені в суперінтерфейс Collection.

Інтерфейс Collection

Інтерфейс collection з пакету java.util описує загальні властивості колекцій List і Set. Він містить методи додавання і видалення елементів, перевірки та перетворення елементів:
boolean add (Object obj) - додає елемент obj в кінець колекції; повертає false, якщо такий елемент в колекції вже є, а колекція не допускає елементи, що повторюються; повертає true, якщо додавання пройшло вдало;
boolean addAll (Collection coll) - додає всі елементи колекції coll в кінець даної колекції;
void clear () - видаляє всі елементи колекції;
boolean contains (Object obj) - перевіряє наявність елемента obj в колекції;
boolean containsAll (Collection coll) - перевіряє наявність всіх елементів колекції coll в даній колекції;
boolean isEmpty () - перевіряє, порожня чи колекція;
iterator iterator () - повертає ітератор даної колекції;
boolean remove (Object obj) - видаляє вказаний елемент з колекції; повертає false, якщо елемент не знайдений, true, якщо видалення пройшло успішно;
boolean removeAll (Collection coll) - видаляє елементи зазначеної колекції, що лежать в даній колекції;
boolean retainAll (Collection coll) - видаляє всі елементи даної колекції, крім елементів колекції coll;
int size () - повертає кількість елементів в колекції;
Object [] toArray () - повертає всі елементи колекції у вигляді масиву;
Objectn toArray (Object [] a) - записує всі елементи колекції в масив а, якщо в ньому достатньо місця.

Інтерфейс List

Інтерфейс List з пакету java.util, розширює інтерфейс Collection, описує методи роботи з впорядкованими колекціями. Іноді їх називають послідовностями (sequence). Елементи такої колекції пронумеровані, починаючи від нуля, до них можна звернутися по індексу. На відміну від колекції Set елементи колекції List можуть повторюватися.
Клас Vector - одна з реалізацій інтерфейсу List.
Інтерфейс List додає до методів інтерфейсу Collection методи, які використовують індекс index елементи:
void add (int index, Object obj) - вставляє елемент obj в позицію index; старі елементи, починаючи з позиції index, зсуваються, їх індекси збільшуються на одиницю;
boolean addAll (int index, Collection coll) - вставляє всі елементи колекції coll;
Object get (int index) - повертає елемент, що знаходиться в позиції index;
int indexOf (Object obj) - повертає індекс першої появи елемента obj в колекції;
int lastindexOf (Object obj) - повертає індекс останньої появи елемента obj в колекції;
Listiterator listiterator () - повертає ітератор колекції;
Listiterator listiterator (int index) - повертає ітератор кінця колекції від позиції index;
Object Set (int index, Object obj) - замінює елемент, що знаходиться в позиції index, елементом obj;
List subListUnt from, int to) - повертає частину колекції від позиції from включно до позиції to виключно.

Інтерфейс Set

Інтерфейс Set з пакету java.util, розширює інтерфейс Collection, описує невпорядковану колекцію, що не містить елементів, що повторюються. Це відповідає математичному поняттю множини (Set). Такі колекції зручні для перевірки наявності або відсутності в елемента властивості, що визначає безліч. Нові методи в інтерфейс Set не додано, просто метод add () не стане додавати ще одну копію елемента, якщо такий елемент вже є в безлічі.
Цей інтерфейс розширено інтерфейсом SortedSet.

Інтерфейс SortedSet

Інтерфейс SortedSet з пакету java.util, розширює інтерфейс Set, описує упорядкований безліч, відсортовану по природному порядку зростання його елементів або один за одним, заданому реалізацією інтерфейсу Comparator.
Елементи не нумеруються, але є поняття першого, останнього, більшого і меншого елемента.
Додаткові методи інтерфейсу відображають ці поняття:
Comparator comparator () - повертає спосіб впорядкування колекції; Object first () - повертає перший, менший елемент колекції;
SortedSet headSet (Object toElement) - повертає початкові, менші елементи до елемента toElement виключно;
Object last () - повертає останній, більший елемент колекції;
SortedSet subSet (Object fromElement, Object toElement) - повертає підмножина колекції від елемента fromElement включно до елемента toElement виключно;
SortedSet tailSet (Object fromElement) - повертає останні, великі елементи колекції від елемента fromElement включно.

Інтерфейс Map

Інтерфейс Map із пакету java.util описує колекцію, що складається з пар "ключ - значення". У кожного ключа тільки одне значення, що відповідає математичному поняттю однозначної функції або відображення.
Таку колекцію часто називають ще словником (dictionary) або асоціативним масивом (associative array).
Звичайний масив - найпростіший приклад словника з наперед заданим числом елементів. Це відображення безлічі перший невід'ємних цілих чисел на безліч елементів масиву, безліч пар "індекс масиву - елемент масиву".
Клас HashTable - одна з реалізацій інтерфейсу березня.
Інтерфейс Map містить методи, що працюють з ключами і значеннями:
boolean containsKey (Object key) - перевіряє наявність ключа key;
boolean containsValue (Object value) - перевіряє наявність значення value;
Set entrySet () - представляє колекцію у вигляді безлічі, кожен елемент якого - пара з даного відображення, з якою можна працювати методами вкладеного інтерфейсу Map.Entry;
Object get (Object key) - повертає значення, яке відповідає ключу key;
Set keySet () - представляє ключі колекції у вигляді безлічі;
Object put (Object key, Object value) - додає пару "key-value", якщо такої пари не було, і замінює значення ключа key, якщо такий ключ вже є в колекції;
void putAll (Map m) - додає до колекції всі пари з відображення m;
Collection values ​​() - представляє всі значення у вигляді колекції.
У інтерфейс Mар вкладений інтерфейс Map.Entry, що містить методи роботи з окремою парою.

Інтерфейс SortedMap

Інтерфейс SortedMap, що розширює інтерфейс Map, описує впорядковану по ключах колекцію березня. Сортування проводиться або в природному порядку зростання ключів, або, в порядку, описуваному в інтерфейсі Comparator.
Елементи не нумеруються, але є поняття більшого і меншого з двох елементів, першого, найменшого, і останнього, самого великого елемента колекції. Ці поняття описуються наступними методами:
Comparator comparator () - повертає спосіб впорядкування колекції;
Object firstKey () - повертає перший, менший елемент колекції;
SortedMap headMap (Object toKey) - повертає початок колекції до елементу з ключем toKey виключно;
Object lastKey () - повертає останній, більший ключ колекції;
SprtedMap subMap (Object fromKey, Object toKey) - повертає частину колекції від елементу з ключем fromKey включно до елементу з ключем toKey виключно;
SortedMap tallMap (Object fromKey) - повертає залишок колекції від елемента fromKey включно.
Ви можете створити свої колекції, реалізувавши розглянуті інтерфейси. Це справа важка, оскільки в інтерфейсах багато методів. Щоб полегшити це завдання, в Java API введені часткові реалізації інтерфейсів - абстрактні класи-колекції.

Абстрактні класи-колекції

Ці класи лежать в пакеті java.util,
Абстрактний клас AbstractGollection реалізує інтерфейс Collection, але залишає нереалізованими методи iterator (), size ().
Абстрактний клас AbstractList реалізує інтерфейс List, але залишає нереалізованим метод get () і успадкований метод size () Цей клас дозволяє реалізувати колекцію спрям доступом до елементів, подібно масиву
Абстрактний клас AbstractSequentialList реалізує інтерфейс List, але залишає нереалізованим метод listiterator (int index) і успадкований метод size (). Даний клас дозволяє реалізувати колекції з послідовним доступом до елементів за допомогою ітератора Listiterator
Абстрактний клас AbstractSet реалізує інтерфейс Set, але залишає нереалізованими методи, успадковані від AbstractCollection
Абстрактний клас AbstractMap реалізує інтерфейс Map, але залишає нереалізованим метод entrySet (),
Нарешті, у складі Java API є повністю реалізовані класи-колекції крім вже розглянутих класів Vector, Stack, Hashtable і Properties, Це класи ArrayList, LinkedList, HashSet, TreeSet, HashMap, TreeMap, WeakHashMap,
Для роботи з цими класами розроблені інтерфейси Iterator,
Listiterator, Comparator І класи Arrays І Collections.
Перед тим як розглянути використання даних класів, обговоримо поняття ітератора.

Інтерфейс Iterator

У 90-х роках було вирішено заносити дані в певну колекцію, приховавши її внутрішню структуру, а для роботи з даними використовувати методи цієї колекції.
Зокрема, завдання обходу поклали на саму колекцію. У Java API введений інтерфейс Iterator, що описує спосіб обходу всіх елементів колекції. У кожній колекції є метод iterator (), який повертає реалізацію інтерфейсу Iterator для зазначеної колекції. Отримавши цю реалізацію, можна обходити колекцію в деякому порядку, визначеному цим ітератором, за допомогою методів, описаних в інтерфейсі Iterator і реалізованих цього ітератора. Подібна техніка використана в класі StringTokenizer.
В інтерфейсі Iterator описані всього три методи:
o логічний метод hasNext () повертає true, якщо обхід ще не завершений;
o метод next () робить поточним наступний елемент колекції і повертає його у вигляді об'єкту класу Object;
o метод remove () видаляє поточний елемент колекції.
Можна уявити собі справу так, що ітератор - це покажчик на елемент колекції. При створенні ітератора покажчик встановлюється перед першим елементом, метод next () переміщає покажчик на перший елемент і показує його. Наступне застосування методу next () переміщає покажчик на другий елемент колекції і показує його. Остання застосування методу next () виводить покажчик за останній елемент колекції.
Метод remove (), мабуть, зайвий, він вже не ставиться до завдання обходу колекції, але дозволяє при перегляді колекції видаляти з неї непотрібні елементи.
Приклад. Використання ітератора вектора
Vector v = new Vector ();
String s = "Рядок, що ми хочемо розібрати на слова.";
StringTokenizer st = new StringTokenizer (s, "\ t \ n \ r ,.");
while (st.hasMoreTokens ()) {
/ / Отримуємо слово і заносимо в вектор.
v.add (st.nextToken ()); / / Додаємо в кінець вектора}
System.out.print * Ln (v.firstElement (}); / / Перший елемент
System.out.println (v.lastElement ()); / / Останній елемент
v.SetSize (4); / / Зменшуємо число елементів
v.add ("зібрати."); / / Додаємо в кінець укороченого вектора
v.Set (3, "знову"); / / Ставимо в позицію 3
for (int i = 0; i <v.sizeO; i + +) / / Перебираємо весь вектор
System.out.print (v.get (i) + ".");
System.out.println (};
Iterator it = v.Iterator (); / / Отримуємо ітератор вектора
try {
while (it.hasNext ()) / / Поки у векторі є елементи,
System.out.println (it.next ()); / / виводимо поточний елемент
} Catch (Exception e) {}

Інтерфейс Listlterator

Інтерфейс ListIterator розширює інтерфейс Iterator, забезпечуючи переміщення по колекції як у прямому, так і в зворотному напрямку. Він може бути реалізований тільки в тих колекціях, в яких є поняття наступного і попереднього елемента і де елементи пронумеровані.
У інтерфейс ListIterator додані наступні методи:
void add (Object element) - додає елемент element перед поточним елементом;
boolean hasPrevious () - повертає true, якщо в колекції є елементи, які стоять перед поточним елементом;
int nextindex () - повертає індекс поточного елемента; якщо поточним є останній елемент колекції, повертає розмір колекції;
Object divvious () - повертає попередній елемент і робить його поточним;
int divvious index () - повертає індекс попереднього елемента;
void Set (Object element) - замінює поточний елемент елементом element;
виконується відразу після next () або divvious ().
Як бачите, ітератори можуть змінювати колекцію, у якій вони працюють, додаючи, видаляючи і замінюючи елементи. Щоб це не призводило до конфліктів, передбачена виняткова ситуація, яка виникає при спробі використання ітераторів паралельно "рідним" методів колекції. Саме тому в наступному прикладі дії з ітератором укладені в блок try (){}- catch (){}.
Приклад з використанням ітератора ListIterator.
Vector v = new Vector ();
String s = "Рядок, що ми хочемо розібрати на слова.";
StringTokenizer st = new StringTokenizer (s, "\ t \ n \ r ,.");
while (st.hasMoreTokens ()) {
/ / Отримуємо слово і заносимо у вектор
v.add (st.nextToken ()); / / Додаємо в кінець вектора
}
ListIterator lit = v.listlterator (); / / Отримуємо ітератор вектора
/ / Покажчик зараз знаходиться перед початком вектора
try {
while (lit.hasNext ()) / / Поки у векторі є елементи
System.out.println (lit.next ()); / / Переходимо до наступного
/ / Елементу і виводимо його
/ / Тепер покажчик за кінцем вектора. Пройдемо до початку
while (lit.hasPrevious ()) System.out.println (lit.divvious ());
}
catch (Exception e) {}
Подивимося тепер, які можливості надають класи-колекції Java2.

Класи, що створюють списки

Клас ArrayList повністю реалізує інтерфейс List і ітератор типу Iterator. Клас ArrayList дуже схожий на клас Vector, має той самий набір методів і може використовуватися в тих же ситуаціях.
У класі ArrayList три конструктори;
ArrayList () - створює порожній об'єкт;
ArrayList (Collection coll) - створює об'єкт, що містить всі елементи колекції coll;
ArrayList (int initCapacity) - створює порожній Об'єкт ємності initCapacity.
Єдина відмінність класу ArrayList від класу Vector полягає в тому, що клас ArrayList НЕ синхронізований. Це означає що одночасна зміна примірника цього класу кількома підпроцесами призведе до непередбачуваних результатів.

Порівняння елементів колекцій

Інтерфейс Comparator описує два методи порівняння:
int compare (Object obji, Object obj2) - повертає від'ємне число, якщо obj1 в якомусь сенсі менше obj2; нуль, якщо вони вважаються рівними; позитивне число, якщо obj1 більше obj2. Цей метод порівняння має властивості тотожності, антисиметричність і транзитивності;
boolean equals (Object obj) - порівнює даний об'єкт з об'єктом obj, повертаючи true, якщо об'єкти збігаються в будь-якому сенсі, заданому цим методом.
Для кожної колекції можна реалізувати ці два методи, задавши конкретний спосіб порівняння елементів, та визначити об'єкт класу SortedMap другий конструктором. Елементи колекції будуть автоматично відсортовані в заданому порядку.

Класи, що створюють множини

Клас HashSet повністю реалізує інтерфейс Set і ітератор типу Iterator. Клас HashSet використовується в тих випадках, коли треба зберігати тільки одну копію кожного елемента.
У класі HashSet чотири конструктора:
HashSet () - створює порожній об'єкт з показником завантаженості 0,75;
HashSet (int capacity) - створює порожній об'єкт з початковою ємкістю capacity і показником завантаженості 0,75;
HashSet (int capacity, float loadFactor) - створює порожній об'єкт з початковою ємкістю capacity і показником завантаженості loadFactor;
HashSet (Collection coll) - створює об'єкт, що містить всі елементи колекції coll, з ємністю, що дорівнює подвоєному числу елементів колекції coll, але не менше 11, і показником завантаженості 0,75.

Впорядковані множини

Клас TreeSet повністю реалізує інтерфейс SortedSet і ітератор типу Iterator. Клас TreeSet реалізований як бінарне дерево пошуку, значить, його елементи зберігаються в упорядкованому вигляді. Це значно прискорює пошук потрібного елемента.
Порядок задається або природним проходженням елементів, або об'єктом, що реалізують інтерфейс порівняння Comparator.
Цей клас зручний при пошуку елемента в безлічі, наприклад, для перевірки, чи має який-небудь елемент властивістю, що визначає безліч.
У класі TreeSet чотири конструктора:
TreeSet () - створює порожній об'єкт з природним порядком елементів;
TreeSet (Comparator с) - створює порожній об'єкт, в якому порядок задається об'єктом порівняння з;
TreeSet (Collection coll) - створює об'єкт, що містить всі елементи колекції coll, з природним порядком її елементів;
TreeSet (SortedMap sf) - створює об'єкт, що містить всі елементи відображення sf, в тому ж порядку.

Дії з колекціями

Колекції призначені для зберігання елементів у зручному для подальшої обробки вигляді. Дуже часто обробка полягає в сортуванні елементів і пошуку потрібного елементу. Ці та інші методи обробки зібрані в клас Collections.
Методи класу Collections
Всі методи класу Collections статичні, ними можна користуватися, не створюючи екземпляри класу Collections
Як завжди в статичних методах, колекція, з якою працює метод, задається його аргументом.
Сортування може бути зроблена тільки у упорядковує колекції, що реалізує інтерфейс List. Для сортування в класі Collections є два методи:
static void sort (List coll) - сортує в природному порядку зростання колекцію coll, що реалізовує інтерфейс List;
static void sort (List coll, Comparator c) - сортує колекцію coll
в порядку, заданому об'єктом с. Після сортування можна здійснити бінарний пошук в колекції:
static int binarySearch (List coll, Object element) - віднаходить елемент element в відсортованої в природному порядку зростання колекції coll і повертає індекс елемента або від'ємне число, якщо елемент не знайдений, а від'ємне число показує індекс, з яким елемент element був би вставлений в колекцію, зі зворотним знаком;
static int binarySearchfList coll, Object element, Comparator c) - те ж, але колекція відсортована в порядку, визначеному об'єктом с.
Чотири методи знаходять найбільший і найменший елементи в упорядковує колекції:
static Object max (Collection coll) - повертає найбільший в природному порядку елемент колекції coll;
static Object max (Collection coll, Comparator c) - те ж в порядку, заданому об'єктом с;
static Object min (Collection coll) - повертає найменший в природному порядку елемент колекції coll;
static Object min (Collection coll, Comparator c) - те ж в порядку, заданому об'єктом с.
Два методи "перемішують" елементи колекції у випадковому порядку:
static void shuffle (List coll) - випадкові числа задаються за умовчанням;
static void shuffle (List coll, Random r) - випадкові числа визначаються об'єктом r.
Метод reverse (List coll) змінює порядок розташування елементів на зворотний.
Метод copy (List from, List to) копіює колекцію from до колекції to.
Метод fill (List coll, Object element) замінює всі елементи існуючої колекції coll елементом element.

Додаток 4. Робота з датами і часом

Робота з датами і времене м
Методи роботи з датами і свідченнями часу зібрані в два класи: Calendar і Date з пакету java.util.
Об'єкт класу Date зберігає число мілісекунд, які минули з 1 січня 1970 00:00:00 за Гринвічем. Це "день народження" UNIX, він називається "Epoch".
Клас Date зручно використовувати для відліку проміжків часу в мілісекундах.
Отримати поточне число мілісекунд, які минули з моменту Epoch на тій машині, де виконується програма, можна статичним методом
System.currentTimeMillis ()
У класі Date два конструктора. Конструктор Date () заносить в створюваний об'єкт поточний час машини, на якій виконується програма, з системних годинах, а конструктор Date (long millisec) - зазначена кількість.
Отримати значення, що зберігається в об'єкті, можна методом long getTime (),
встановити нове значення - методом setTime (long newTime).
Три логічних методу порівнюють відліки часу:
boolean after (long when) - повертає true, якщо час when більше даного;
boolean before (long when) - повертає true, якщо час when менше даного;
boolean after (Object when) - повертає true, якщо часи when - об'єкта класca Date і дане збігаються.
Ще два методи, порівнюючи відліки часу, повертають негативне число типу int, якщо даний час менше аргументу when; нуль, якщо часи збігаються; позитивне число, якщо даний час більше аргументу when:
int compareTo (Date when);
int compareTo (Оbject when) - якщо when не відноситься до об'єктів класу Date, створюється виняткова ситуація.
Перетворення мілісекунд, що зберігаються в об'єктах класу Date, в поточний час і дату проводиться методами класу Calendar.
Клас Calendar
Клас Calendar - абстрактний, в ньому зібрані загальні властивості календарів: юліанського, григоріанського, місячного. У Java API поки є тільки одна його реалізація - підклас GregorianCalendar.
Оскільки Сalendar - абстрактний клас, його екземпляри створюються чотирма статичними методами за заданою локалі і / або часовому поясу:
Calendar getlnstance ()
Calendar getlnstance (Locale loc)
Calendar getlnstance (TimeZone tz)
Calendar getlnstance (TimeZone tz, Locale loc)
Для роботи з місяцями визначені цілочисельні константи від JANUARY
до DECEMBER, для роботи з днями тижня - константи MONDAY до SUNDAY.
Перший день тижня можна дізнатися методом int getFirstDayOfWeek (), a встановити - методом setFirstDayOfWeek (int day), наприклад:
setFirstDayOfWeek (Calendar.MONDAY)
Решта методи дозволяють переглянути час і часовий пояс або встановити їх.
Представлення дати і часу
Різні способи представлення дат і показань часу можна здійснити методами, зібраними в абстрактний клас DateFormat і його підклас SimpleDateFormat з пакету Java. text.
Клас DateFormat пропонує чотири стилі представлення дати і часу:
стиль SHORT представляє дату і час у короткому числовому вигляді: 27.04.01 17:32; в локалі США: 4/27/01 5:32 РМ;
стиль MEDIUM задає рік чотирма цифрами і показує секунди: 27.04.2001 17:32:45; в локалі США місяць видається трьома літерами;
стиль LONG представляє місяць словом і додає часовий пояс: 27 квітня 2001 17:32:45 GMT +03 .- 00;
стиль FULL в російській локалі такий же, як і стиль LONG; в локалі США додається ще день тижня.
Є ще стиль DEFAULT, що співпадає зі стилем MEDIUM.
При створенні об'єкту класу SimpieDateFormat можна задати в конструкторі шаблон, що визначає будь-який інший формат, наприклад:
SimpieDateFormat sdf = new SimpieDateFormat ("dd-MM-yyyy hh.mm"); System.out.println (sdf.format (new Date ()));
Отримаємо висновок у такому вигляді: 27-07-2004 17.32.

Додаток 5. Файловий ввід / вивід.

Оскільки файли в більшості сучасних операційних систем розуміються як послідовність байтів, для файлового введення / виведення створюються байтові потоки за допомогою класів FileInputStream і FileOutputStream. Дуже багато файлів містять тексти, складені з символів. Незважаючи на те, що символи можуть зберігатися в кодуванні Unicode, ці тексти найчастіше записані в байтових кодуваннях. Тому і для текстових файлів можна використовувати байтові потоки. У такому випадку з боку програми доведеться організувати перетворення байтів в символи і назад.
Щоб полегшити це перетворення, в пакет java.io введені класи FileReader і FileWriter. Вони організують перетворення потоку: з боку програми потоки символьні, з боку файлу - байтові. Це відбувається тому, що дані класи розширюють класи InputStreamReader і OutputstreamWriter, відповідно, значить, містять "перехідне кільце" всередині себе.
Незважаючи на відмінність потоків, використання класів файлового введення / виводу дуже схоже.
У конструкторах всіх чотирьох файлових потоків задається ім'я файлу у вигляді рядка типу String або посилання на об'єкт класу File. Конструктори не тільки створюють об'єкт, а й відшукують файл і відкривають його. Наприклад:
FileInputStream fis = new FileInputStream ("C: \ \ PrWr.Java");
FileReader fr = new FileReader ("D: \ \ jdkl.3 \ \ src \ \ PrWr.Java");
При невдачі викидається виключення класу FileNotFoundException, але конструктор класу FileWriter викидає більш загальне виключення IOException.
Після відкриття вихідного потоку типу FileWriter або FileOutputStream вміст файлу, якщо він був не порожній, стирається. Для того щоб можна було робити запис у кінець файлу, і в тому і в іншому класі передбачений конструктор з двома аргументами. Якщо другий аргумент дорівнює true, то відбувається дозапис в кінець файлу, якщо false, то файл заповнюється новою інформацією. Наприклад:
FileWriter fw = new FileWriter ("c: \ \ 8.txt", true);
FileOutputStream fos = new FileOutputStream ("D: \ \ samples \ \ newfile.txt");
Відразу після виконання конструктора можна читати файл:
fis.read (); fr.read ();
або записувати в нього:
fos.write ((char) с); fw.write ((char) с);
Після закінчення роботи з файлом потік слід закрити методом close ().
Перетворення потоків у класах FileReader і FileWriter виконується за кодовою таблиць встановленої на комп'ютері локалі. Для правильного вводу кирилиці треба застосовувати FileReader, a нe FileInputStream. Якщо файл містить текст у кодуванні, відмінною від локальної кодування, то доведеться вставляти "перехідне кільце" вручну, як це може робитися для консолі, наприклад:
InputStreamReader isr = new InputStreamReader (fis, "KOI8_R"));
Байтовий потік fis визначений вище.
Набуття властивостей файлу
У конструкторах класів файлового введення / виводу, описаних у попередньому розділі, вказувалося ім'я файлу у вигляді рядка. При цьому залишалося невідомим, чи існує файл, чи дозволений до, нього доступ, яка довжина файлу.
Отримати такі відомості можна від попередньо створеного екземпляра класу File, що містить відомості про файл. У конструкторі цього класу
File (String filename)
вказується шлях до файлу або каталога, записаний за правилами операційної системи.
Конструктор не перевіряє, чи існує файл з таким ім'ям, тому після створення об'єкта слід це перевірити логічним методом exists ().
Клас File містить близько сорока методів, що дозволяють дізнатися різні властивості файлу або каталогу.
Перш за все, логічними методами isFile (), isDirectory () можна з'ясувати, чи є шлях, вказаний в конструкторі, шляхом до файлу або каталогу.
Для каталогу можна отримати його вміст - список імен файлів і підкаталогів-методом list (), що повертає масив рядків String []. Можна отримати такий же список у вигляді масиву об'єктів класу File [] методом listFiles ().
Якщо каталог з вказаним в конструкторі шляхом не існує, його можна створити логічним методом mkdir (). Цей метод повертає true, якщо каталог вдалося створити. Логічний метод mkdirs () створює ще і всі неіснуючі каталоги, зазначені в дорозі.
Логічні методи canRead (), canwrite () показують права доступу до файлу.
Файл можна перейменувати логічним методом renameTo (File newName) або видалити логічним методом delete (). Ці методи повертають true, якщо операція пройшла вдало.
Якщо файл з вказаним в конструкторі шляхом не існує, його можна створити логічним методом createNewFile (), що повертає true, якщо файл не існував, і його вдалося створити, і false, якщо файл вже існував.
Кілька методів getxxx () повертають ім'я файлу, ім'я каталогу й інші відомості про шлях до файлу. Ці методи корисні в тих випадках, коли посилання на об'єкт класу File повертається іншими методами і потрібні відомості про файл. Нарешті, метод toURL () повертає шлях до файлу у формі URL.
Буферизованная введення / висновок
Операції введення / виводу в порівнянні з операціями в оперативній пам'яті виконуються дуже повільно. Для компенсації в оперативній пам'яті виділяється деяка проміжна область - буфер, в якій поступово накопичується інформація. Коли буфер заповнений, його вміст швидко переноситься процесором, буфер очищується і знову заповнюється інформацією.
Класи файлового введення / виводу не займаються буферизацией. Для цієї мети є чотири спеціальних класу BufferedXxx. Вони приєднуються до потокам уведення / виводу як "перехідне кільце", наприклад:
BufferedReader br = new BufferedReader (isr);
BufferedWriter bw = new BufferedWriter (fw);
Потоки isr ​​і fw визначені вище.
Дана програма читає текстовий файл, написаний у кодуванні ср866, і записує його вміст у файл у кодуванні Cp1251. При читанні і запису застосовується буферизація.
import java.io. *;
class DOStoWindows {
public static void main (String [] args) throws IOException {
BufferedReader br = new BufferedReader (
new InputStreamReader (
new FileInputStream d: \ \ dos.txt, "Cp866"));
BufferedWriter bw = new BufferedWriter (
new OutputStreamWriter (
new FileOutputStream d: \ \ windows.txt, "Cp1251"));
int с = 0;
while ((c = br.read ())! = -1) bw.write ((char) c);
br.close (); bw.close ();
System.out.println ("Усі OK.");
}
}

Додаток 6. Обробка винятків
Виняткові ситуації (exceptions) можуть виникнути під час виконання (runtime) програми, перервавши її звичайний хід. До них відноситься розподіл на нуль, відсутність завантаження, негативний або вийшов за верхню межу індекс масиву, переповнення виділеної пам'яті і маса інших неприємностей, які можуть трапитися в самий невідповідний момент.
В об'єктно-орієнтованих мовах програмування прийнятий такий підхід. При виникненні виняткової ситуації виконуюча система створює об'єкт певного класу, відповідного виниклої ситуації, що містить відомості про те, що, де і коли сталося. Цей об'єкт передається на обробку програмі, в якій виникло виключення. Якщо програма не обробляє виключення, то об'єкт повертається оброблювачу за замовчуванням виконуючою системи. Оброблювач надходить дуже просто: виводить на консоль повідомлення про події вилучення та припиняє виконання програми.

Блоки перехоплення виключення

Ми можемо перехопити і обробити виняток у програмі. При описі обробки застосовується бейсбольна термінологія. Кажуть, що виконуюча система або програма "викидає" (throws) об'єкт-виняток. Цей об'єкт "пролітає" через всю програму, з'явившись спочатку в тому методі, де сталося виняток, а програма в одному або декількох місцях намагається (try) його "перехопити" (catch) і обробити. Обробку можна зробити повністю в одному місці, а можна обробити виключення в одному місці, викинути знову, перехопити в іншому місці і обробляти далі.
Для того щоб спробувати (try) перехопити (catch) об'єкт-виключення, треба весь код програми, в якому може виникнути виняткова ситуація, охопити оператором try {} catch () {}. Кожен блок catch () {} перехоплює виняток лише одного типу, того, який зазначений у його аргументі. Але можна написати кілька блоків catch () {} для перехоплення декількох типів виключень.
Після блоків перехоплення може бути вставлений ще один, необов'язковий блок finally (). Він призначений для виконання дій, які треба виконати обов'язково, щоб не трапилося. Все, що написано в цьому блоці, буде виконано і при виникненні виключення, і при звичайному ході програми, і навіть якщо вихід з блоку try {} здійснюється оператором return.
Якщо в операторі обробки винятків є блок finally {}, то блок catch () {} може бути відсутнім, тобто можна не перехоплювати виняток, але при його виникненні все-таки виконати якісь обов'язкові дії. Порожній блок catch (){}, в якому між фігурними дужками немає нічого, навіть пробілу, теж вважається обробкою винятку і призводить до того, що виконання програми не припиниться.

Частина заголовка методу throws

Та обставина, що метод не обробляє виникає в ньому виняток, а викидає (throws) його, слід відзначати в заголовку методу службовим словом throws і зазначенням класу винятки:
private static void f (int n) throws ArithmeticException {
System.out.println ("10 / n =" + (10 / n));
}
Виняток ArithmeticException випадає, наприклад, при поділі на нуль.
Справа в тому, що специфікація JLS ділить всі винятки на перевіряються (checked), ті, які перевіряє компілятор, і неперевіряючі (unchecked). При перевірці компілятор зауважує необроблені в методах і конструкторах винятку і вважає помилкою відсутність в заголовку таких методів і конструкторів позначки throws. Саме для запобігання подібних помилок вставляються до лістингів блоки обробки винятків.
Так ось, виключення класу RuntimeException і його підкласів, одним з яких є ArithmeticException, непроверяемой, для них позначка throws необов'язкова. Ще одне велике сімейство непроверяемой виключення складає клас Error і його розширення.
Чому компілятор не перевіряє ці типи винятків? Причина в тому, що виключення класу RuntimeException свідчать про помилки в програмі, і єдино розумний метод їх обробки - виправити вихідний текст програми і перекомпілювати її. Що стосується класу Error, то ці виключення дуже важко локалізувати і на стадії компіляції неможливо визначити місце їх появи.
Навпаки, виникнення перевіряється виключення показує, що програма недостатньо продумана, не всі можливі ситуації описані. Така програма повинна бути доопрацьована, про що і нагадує компілятор.
Якщо метод або конструктор викидає кілька винятків, то їх треба перерахувати через кому після слова throws.

Оператор throw

Цей оператор дуже простий: після слова throw через пробіл записується об'єкт класу-винятки. Досить часто він створюється прямо в операторі throw, наприклад:
throw new ArithmeticException ();
Оператор можна записати в будь-якому місці програми. Він негайно викидає записаний у ньому об'єкт-виняток і далі обробка цього виключення йде як зазвичай, буцімто тут сталося розподіл на нуль або інше дію, яка викликала виняток класу ArithmeticException.
Отже, кожен блок catch () і перехоплює один певний тип винятків. Якщо потрібно однаково обробити кілька типів виключень, то можна скористатися тим, що класи-виключення утворюють ієрархію. Таким чином, переміщаючись по ієрархії класів-виключень, ми можемо обробляти відразу більш-менш великі сукупності винятків. Розглянемо докладніше ієрархію класів-виключень.

Ієрархія класів-виключень

Всі класи-виключення розширюють клас Throwable - безпосереднє розширення класу Object.
У класу Throwable і у всіх його розширень за традиції два конструктора:
· Throwable () - конструктор за умовчанням;
· Throwable (String message) - створюваний об'єкт буде мати будь-повідомлення message.
Записане в конструкторі повідомлення можна отримати потім методом getMessage (). Якщо об'єкт створювався конструктором за умовчанням, то даний метод поверне null.
Метод toString () повертає короткий опис події.
Три методи виводять повідомлення про всі методи, що зустрілися по шляху "польоту" виключення:
· PrintstackTrace () - виводить повідомлення в стандартний висновок, як правило, це консоль;
· PrintStackTrace (PrintStream stream) - виводить повідомлення в байтовий потік stream;
· PrintStackTrace (PrintWriter stream) - виводить повідомлення в символьний потік stream.
У класу Throwable два безпосередніх спадкоємця - класи Error і Exception. Вони не додають нових методів, а служать для поділу класів-виключень на два великих сімейства - сімейство класів-помилок (error) і сімейство власне класів-виключень (exception).
Класи-помилки, що розширюють клас Error, свідчать про виникнення складних ситуацій у віртуальній машині Java. Їх обробка вимагає глибокого розуміння всіх тонкощів роботи JVM. Її не рекомендується виконувати в звичайній програмі. Не радять навіть викидати помилки оператором throw. He слід робити свої класи-виключення розширеннями класу Error або якогось його підкласу.
Імена класів-помилок, за угодою, закінчуються словом Error.
Класи-виключення, що розширюють клас Exception, відзначають виникнення звичайної нештатної ситуації, яку можна і навіть потрібно обробити. Такі винятки слід викинути оператором throw. Класів-виключень дуже багато, більше двохсот. Вони розкидані буквально по всіх пакетах J2SDK. У більшості випадків ви здатні підібрати готовий клас-виключення для обробки виняткових ситуацій у своїй програмі. При бажанні можна створити і свій клас-виключення, розширивши клас Exception або будь-якої його підклас.
Серед класів-виключень виділяється клас RuntimeException - пряме розширення класу Exception. У ньому і його підкласах наголошуються виключення, що виникли при роботі JVM, але не настільки серйозні, як помилки. Їх можна обробляти і викидати, розширювати своїми класами, але краще довірити це JVM, оскільки найчастіше це просто помилка в програмі, яку треба виправити. Особливість виключень даного класу в тому, що їх не треба відзначати в заголовку методу позначкою throws.
Імена класів-виключень, за угодою, закінчуються словом Exception.

Порядок обробки виключень

Блоки catch () {} перехоплюють виключення в порядку написання цих блоків. Це правило призводить до цікавих результатів.
try {
/ / Оператори, що викликають виключення
} Catch (Exception e) {
/ / Якась обробка
} Catch (RuntimeException re) {
/ / Ніколи не буде виконано!
}
Другий блок не буде виконуватися, оскільки виняток типу RuntimeException є винятком загального типу Exception і буде перехоплюватися попереднім блоком catch () {}.
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Методичка
131.2кб. | скачати


Схожі роботи:
Успадкування та класи-колекції
Успадкування в російському законодавстві
Спадщина Інститут Успадкування
Спадкування за заповітом 2 Вивчення успадкування
Порядок і умови успадкування за заповітом
Особливості успадкування майна у підприємницькій сфері
Поняття підприємства як майнового комплексу та правові питання його успадкування
Музейні колекції та мистецький ринок
Класи і страти
© Усі права захищені
написати до нас