Реферати

Навчальний посібник: Спадкування і колекція^-класи-колекції

Способи виходна на зовнішні ринки. ГОУ ВПО РОСІЙСЬКИЙ ЕКОНОМІЧНИЙ УНІВЕРСИТЕТ ім. Г. В. ПЛЕХАНОВА Кафедра маркетингу Доповідь по дисципліні "Міжнародний маркетинг" на тему: "Способи виходу на зовнішні ринки"

Розвиток вітчизняної школи менеджменту. АКАДЕМІЯ ПРАЦІ і СОЦІАЛЬНИХ ВІДНОСИН КАФЕДРА ЕКОНОМІКИ І МЕНЕДЖМЕНТУ Курсова робота ОСНОВАМ МЕНЕДЖМЕНТУ На тему: РОЗВИТОК ВІТЧИЗНЯНОЇ ШКОЛИ МЕНЕДЖМЕНТУ:

Toolbook II Assistant Version 6.0. Вимоги до системи проектування "електронного підручника". Основні можливості ToolBook. Вимоги до побудови тесту. Надійність. Дискриминативность.

Ланской, Олександр Дмитрович. Олександр Дмитрович Ланской (8 березня 1758, Смоленська губернія - 25 червня 1784, Царське Село) - генерал-поручик, генерал-ад'ютант, дійсний камергер і кавалер орденів Святого Олександра Невського, Білого орла, Святого Станіслава, Сятой Ганни і Полярної зірки; фаворит Катерини II.

Закон синергії на прикладі ОАО Хлебпром. ФЕДЕРАЛЬНЕ АГЕНТСТВО ПО УТВОРЕННЮ УРАЛЬСЬКИЙ^-ПІВДЕННО-УРАЛЬСЬКИЙ ДЕРЖАВНИЙ УНІВЕРСИТЕТ ФАКУЛЬТЕТ ПРАВА І ФІНАНСІВ КОНТРОЛЬНА РОБОТА З курсу: Теорія організації

Факультет "Інформатика і системи керування"

Методичні вказівки до лабораторної роботи

за курсом "Розподілені системи обробки інформації"

Спадкування і колекція^-класи-колекції

Москва 2004 р.

Зміст

Ціль роботи.. 3

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

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

Завдання 1 3

Завдання 2 4

Зміст звіту. 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. Як потрібно змінити програму, щоб після оголошення методу publicstaticvoidmain(String[] args) не потрібно було б записувати throwsIOException.

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.

importjava.io.*;//підключення пакета з класами введення/висновку

importjava.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:\\output.txt"));

//Вихідний потік - у файл d:\output.txt

//ініціалізація екземпляра класу, що реалізує інтерфейс колекцій

intc = 0;

Datebefore = newDate(); //зафіксували час перед обробкою

while ((c = br.read()) != -1) { //поки не досягнуть кінець файлу d:\input.txt

//обробка

/*

наприклад, якщо раніше визначений рядок Strings="";

те можна записати s+=(char)c;

Тоді весь уміст файлу d:\input.txt буде записано в рядок s

*/

}

br.close(); //закриваємо вхідний потік після читання і попередньої обробки

for (/*цикл*/){

//обробка і запис у вихідний потік

bw.write(/*слово*/+" "+/*число*/+"\r\n");

}

bw.close(); //закриваємо вихідний потік після запису файлу

Dateafter = newDate(); //фіксуємо час після обробки

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 оnсе, 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), перевизначений із класу Оbjесt, повертає 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 (stringsub), що повертає індекс першого символу останнього входження подстроки sub у рядок this чи (-1), якщо подстрока sub не входить у рядок this.

Останнє входження подстроки sub не у весь рядок this, а тільки в її початок до індексу ind можна відшукати методом lastIndexof(String stf, int ind). Якщо ind більше довжини рядка, то пошук йде від кінця рядка, якщо ind < 0, то повертається -1.

Перераховані вище методи створюють виняткову ситуацію, якщо

sub == null.

Якщо ви хочете здійснити пошук, що не враховує регістр букв, зміните попередньо регістр усіх символів рядка.

Як змінити регістр символів

Метод toLowerCase() повертає новий рядок, у якій усі букви переведені в нижній регістр, тобто зроблені рядковими.

Метод toUpperCase () повертає новий рядок, у якій усі букви переведені у верхній регістр, тобто зроблені прописними.

При цьому використовується локальна кодова таблиця за замовчуванням. Якщо потрібна інша локаль, то застосовуються методи toLowerCase(Localeloc) і 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.utіlвходит простий классStrіngTокеnіzеr, що полегшує розбір рядків.

Клас StringTokenizer

Клас StringTokenizer з пакета java.util невеликий, у ньому три конструктори і шість методів.

Перший конструктор StringTokenizer (String str) створює об'єкт, готовий розбити рядок str на слова, розділені пробілами, символами табуляцій '\t', перекладу рядка '\n' і повернення каретки '\r'. Роздільники не включаються в число слів.

Другий конструкторStrіngTокеnіzеr (Stringstr, String delimeters) задає роздільники другим параметром delimeters, наприклад:

StringTokenizer("Страчувати, не можна: ні", " \t\n\r,:-");

Тут перший роздільник - пробіл. Потім йдуть символ табуляції, символ перекладу рядка, символ повернення каретки, кома, двокрапка, дефіс. Порядок розташування роздільників у рядку delimeters не має значення. Роздільники не включаються в число слів.

Третій конструктор дозволяє включити роздільники в число слів:

StringTokenizer(String str, String delimeters, boolean flag);

У розборі рядка на слова активно беруть участь наступні методи:

ометод nextToken() повертає у виді рядка наступне слово.

ометод hasMoreTokens() повертає true, якщо в рядку ще є слова, і false, якщо слів більше немає.

ометод countTokens() повертає число слів, що залишилися.

ометод nextToken(string newDelimeters) дозволяє "на ходу" змінювати роздільники. Наступне слово буде виділено по нових роздільниках newDelimeters; нові роздільники діють далі замість старих роздільників, визначених у чи конструкторі попередньому методі nextToken().

ометоди 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) дозволяє додати елемент у кінець вектора.

Методомаdd (intindex, Objectelement) можна вставити елемент у зазначене місце 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() чи обнулив размервектораметодомsеtSіzе(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 і = 0; і < v.size; і++) // Перебираемвесьвектор

System.out.print(v.get(і) + " ");

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() видаляє всі елементи, очищаючи таблицю.

Приклад програми "Телефонний довідник".

importjava.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

КлассрrореrtіеsрасширяетклассHаshtаblе. Він призначений в основному для введення і висновку пара властивостей системи і їхніх значень. Пари зберігаються у виді рядків типу String. У класі Properties два конструктори:

Properties() - створює порожній об'єкт;

Properties (Properties default) - створює об'єкт із заданими парами властивостей default.

Крім успадкованих від класу Hashtable методів у класі Properties є ще наступні методи.

Два методи, що повертають значення ключа-рядка у виді рядка:

- String getProperty (String key) - возвращаетзначениепоключукеу;

- String getProperty(String.key, String defaultValue) - возвращаетзначениепоключукеу; еслитакогоключанет, возвращаетсяdеfаultVаluе.

Метод 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) - уставляетвсеелементиколлекциисоll;

Object get(int index) - повертає елемент, що знаходиться в позиції index;

int indexOf(Object obj) - повертає індекс першої появи елемента obj у колекції;

int lastindexOf (Object obj) - повертає індекс останньої появи елемента obj у колекції;

Listiterator listiterator () - повертає итератор колекції;

Listiterator listiterator (int index) - повертає итератор кінця коллекцииот позицииіndех;

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)-проверяетналичиеключакеу;

boolean containsValue (Object value) - проверяетналичиезначенияvаluе;

Set entrySet () - представляє колекцію у виді безлічі, кожен елемент якого - пари з даного відображення, з яким можна працювати методами вкладеного інтерфейсу Map.Entry;

Object get (Object key) - повертає значення, що відповідає ключу key;

Set keySet() - представляє ключі колекції у виді безлічі;

Objectput(Objectkey, Objectvalue) - додає пари "key- value", якщо такої пари не було, і заміняє значення ключа key, якщо такий ключ уже є в колекції;

void putAll (Map m) - додає до колекції усі пари з відображення m;

Collection values() - представляє всі значення у виді колекції.

В інтерфейс Мар вкладений інтерфейс 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 Иклассиаrrауs И 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 і = 0; і < v.size; і++) // Перебираемвесьвектор

System.out.print(v.get(і) + ".");

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 previous() - повертає попередній елемент і робить його поточним;

int previous index() - повертає індекс попереднього елемента;

void Set (Object element)-заміняє поточний елемент елементом element;

виконується відразу після next() чи previous().

Як бачите, итератори можуть змінювати колекцію, у якій вони працюють, додаючи, видаляючи і заміняючи елементи. Щоб це не приводило до конфліктів, передбачена виняткова ситуація, що виникає при спробі використання итераторов паралельно "рідним" методам колекції. Саме тому в наступному прикладі дії з итератором укладені в блок 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.previous());

}

catch (Exceptione) {}

Подивимося тепер, які можливості надають класу-колекції Java2.

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

Клас ArrayList цілком реалізує інтерфейс List і итератор типу Iterator. Клас ArrayList дуже схожий на клас Vector, має той же набір методів і може використовуватися в тих же ситуаціях.

У класі ArrayList три конструктори;

ArrayList() - створює порожній об'єкт;

ArrayList(Collection coll) - створює об'єкт, що містить всі елементи колекції coll;

ArrayList (int initCapacity) - создаетпустойобъектемкостиіnіtсарасіtу.

Єдина відмінність класу 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) - сортируетколлекциюсоll

у порядку, заданому об'єктом с. Після сортування можна здійснити бінарний пошук у колекції:

static int binarySearch(List coll, Object element) - відшукує елементеlемеnt у відсортованій у природному порядку зростання колекції coll і повертає індекс чи елемента негативне число, якщо елемент не знайдений; негативне число показує індекс, з яким елемент element був би вставлений у колекцію, зі зворотним знаком;

static int binarySearchfList coll, Object element, Comparator c) - те ж, але колекція відсортована в порядку, визначеному об'єктом с.

Чотири методи знаходять найбільший і найменший елементи в колекції, що упорядковується:

static Object max (Collection coll) - повертає найбільший у природному порядку елемент колекції coll;

staticObjectmax (Collectioncoll, Comparatorc) - те ж у порядку, заданому об'єктом з;

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(),

установити нове значення - методомsеtTіме(long newTime).

Три логічних методи порівнюють отсчети часу:

boolean after (long when) - повертає true, якщо времяwhеn більше даного;

boolean before (long when) - повертає true, якщо час when менше даного;

boolean after (Object when) - повертає true, якщо часи when - об'єкта класу Date і дане збігаються.

Ще два методи, порівнюючи отсчети часу, повертають негативне число типу int, якщо даний час менше аргументу when; нуль, якщо часи збігаються; позитивне число, якщо даний час більше аргументу when:

int compareTo(Date when);

int compareTo(Оbjесt when) - якщо when не відноситься до об'єктів класу Date, створюється виняткова ситуація.

Перетворення миллисекунд, що зберігаються в об'єктах класу Date, у поточне час і дату виробляється методами класу Calendar.

Клас Calendar

Клас Calendar - абстрактний, у ньому зібрані загальні властивості календарів: юліанського, григорианского, місячного. У Java API поки є тільки одна його реалізація - підклас GregorianCalendar.

Оскільки Саlеndаr - абстрактний клас, його екземпляри створюються чотирма статичними методами по заданої локали і/чи вартовому поясу:

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 не 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. При читанні і записі застосовується буферизация.

importjava.io.*;

classDOStoWindows{

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)) ;

}

Виключення Аrіthмеtісехсерtіоnвипадает, наприклад, при розподілі на нуль.

Справа в тім, що специфікація 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 () {}.