SortedSet tailSet(E fromElement);

Метод. Методы headSet(E element) и tailSet(E element, boolean inclusive) возвращают то множество элементов, которое меньше либо больше element соответственно. Если inclusive равно true, то элемент включается в найденное множество и не включается в противном случае.

В следующем примере показано использование интерфейса NavigableSet.

/* # 13 : иcпользование множества NavigableSet: NavigableSetTest.java */

package by.bsu.chapt10;

import java.util.*;

public class NavigableSetTest {

public static void main(String[] args) {

HashSet<String> city = new HashSet<String>();

city.add("Minsk");

city.add("Mosсow");

city.add("Polotsk");

city.add("Brest");

NavigableSet<String> ns = new TreeSet<String>(city);

System.out.println("All: " + ns);

System.out.println("Between Minsk and Polotsk: "

+ ns.subSet("Minsk","Polotsk"));

System.out.println("Before Minsk: "

+ ns.headSet("Minsk"));

System.out.println("After Minsk: "

+ ns.tailSet("Minsk",false));

}

}

В результате на консоль будет выведено:

All: [Brest, Minsk, Mosсow, Polotsk]

Between Minsk and Polotsk: [Minsk, Mosсow]

Before Minsk: [Brest]

After Minsk: [Mosсow, Polotsk]

Карты отображений

Карта отображений – это объект, который хранит пару “ключ-значение”. Поиск объекта (значения) облегчается по сравнению с множествами за счет того, что его можно найти по его уникальному ключу. Уникальность объектов-ключей должна обеспечиваться переопределением методов hashCode() и equals() пользовательским классом. Если элемент с указанным ключом отсутствует в карте, то возвращается значение null.

Классы карт отображений:

AbstractMap<K,V> – реализует интерфейс Map<K,V>;

HashMap<K,V> – расширяет AbstractMap<K,V>, используя хэш-таблицу, в которой ключи отсортированы относительно значений их хэш-кодов;

TreeMap<K,V> – расширяет AbstractMap<K,V>, используя дерево, где ключи расположены в виде дерева поиска в строгом порядке.

WeakHashMap<K,V> позволяет механизму сборки мусора удалять из карты значения по ключу, ссылка на который вышла из области видимости приложения.

LinkedHashMap<K,V> запоминает порядок добавления объектов в карту и образует при этом дважды связанный список ключей. Этот механизм эффективен, только если превышен коэффициент загруженности карты при работе с кэш-памятью и др.

SortedSet tailSet(E fromElement); - student2.ru

Рис. 3. Иерархия наследования карт

Для класса IdentityHashMap<K,V> хэш-коды объектов-ключей вычисляются методом System.identityHashCode() по адресу объекта в памяти, в отличие от обычного значения hashCode(), вычисляемого сугубо по содержимому самого объекта.

Интерфейсы карт:

Map<K,V> – отображает уникальные ключи и значения;

Map.Entry<K,V> – описывает пару “ключ-значение”;

SortedMap<K,V> – содержит отсортированные ключи и значения;

NavigableMap<K,V> – добавляет новые возможности поиска по ключу.

Интерфейс Map<K,V> содержит следующие методы:

void clear()– удаляет все пары из вызываемой карты;

boolean containsKey(Object key) – возвращает true, если вызывающая карта содержит key как ключ;

boolean containsValue(Object value) – возвращает true, если вызывающая карта содержит value как значение;

Set<Map.Entry<K,V>> entrySet() – возвращает множество, содержащее значения карты;

Set<K> keySet() – возвращает множество ключей;

V get(Object obj) – возвращает значение, связанное с ключом obj;

V put(K key, V value) – помещает ключ key и значение value в вызывающую карту. При добавлении в карту элемента с существующим ключом произойдет замена текущего элемента новым. При этом метод возвратит заменяемый элемент;

void putAll(Map <? extends K, ? extends V> t) – помещает коллекцию t в вызывающую карту;

V remove(Object key) – удаляет пару “ключ-значение” по ключу key;

Collection<V> values() – возвращает коллекцию, содержащую значения карты.

Интерфейс Map.Entry<K,V> содержит следующие методы:

K getKey() – возвращает ключ текущего входа;

V getValue() – возвращает значение текущего входа;

V setValue(V obj) – устанавливает значение объекта obj в текущем входе.

В примере показаны способы создания хэш-карты и доступа к ее
элементам.

/* # 14 : создание хэш-карты и замена элемента по ключу:

DemoHashMap.java */

packagechapt10;

import java.util.*;

public class DemoHashMap {

public static void main(String[] args){

HashMap<Integer, String> hm =

new HashMap<Integer, String>(5);

for (int i = 11; i < 15; i++) {

hm.put(i, i + "EL");

}

System.out.println(hm);

hm.put(12, "14EL");

System.out.println(hm + "с заменой элемента");

String a = hm.get(12);

System.out.println(a + " - найден по ключу '12'");

/* вывод хэш-таблицы с помощью методов интерфейса

Map.Entry<K,V> */

Set<Map.Entry<Integer, String>> setvalue =

hm.entrySet();

System.out.println(setvalue);

Iterator<Map.Entry<Integer, String>> i =

setvalue.iterator();

while (i.hasNext()) {

Map.Entry<Integer, String> me = i.next();

System.out.print(me.getKey()+" : ");

System.out.println(me.getValue());

}

}

}

{13=13EL, 14=14EL, 12=12EL, 11=11EL}

{13=13EL, 14=14EL, 12=14EL, 11=11EL}с заменой элемента

14EL - найден по ключу '12'

[13=13EL, 14=14EL, 12=14EL, 11=11EL]

EL

EL

EL

EL

Ниже приведен фрагмент кода корпоративной системы, где продемонстрированы возможности класса HashMap<K,V> и интерфейса Map.Entry<K,V> при определении прав пользователей.

/* # 15 : применение коллекций при проверке доступа в систему :

DemoSecurity.java */

packagechapt10;

import java.util.*;

public class DemoSecurity {

public static void main(String[] args) {

CheckRight.startUsing(2041, "Артем");

CheckRight.startUsing(2420, "Ярослав");

/*

*добавление еще одного пользователя и

* проверка его на возможность доступа

*/

CheckRight.startUsing(2437, "Анастасия");

CheckRight.startUsing(2041, "Артем");

}

}

/* пример # 16 : класс проверки доступа в систему: CheckRight.java */

packagechapt10;

import java.util.*;

public class CheckRight {

private static HashMap<Integer, String> map =

new HashMap<Integer, String> ();

public static void startUsing(int id, String name) {

if (canUse(id)){

map.put(id, name);

System.out.println("доступ разрешен");

} else{

System.out.println("в доступе отказано");

}

}

public static boolean canUse(int id) {

final int MAX_NUM = 2; // заменить 2 на 3

int currNum = 0;

if (!map.containsKey(id))

currNum = map.size();

returncurrNum < MAX_NUM;

}

}

В результате будет выведено:

Доступ разрешен

Доступ разрешен

В доступе отказано

Доступ разрешен,

так как доступ в систему разрешен одновременно только для двух пользователей. Если в коде изменить значение константы MAX_NUM на большее, чем 2, то новый пользователь получит права доступа.

Класс EnumMap<K extends Enum<K>, V> в качестве ключа может принимать только объекты, принадлежащие одному типу enum, который должен быть определен при создании коллекции. Специально организован для обеспечения максимальной скорости доступа к элементам коллекции.

/* # 17 : пример работы с классом EnumMap: UseEnumMap.java */

package chapt10;

import java.util.EnumMap;

enum User {

STUDENT, TUTOR, INSTRUCTOR, DEAN

}

class UserPriority {

private int priority;

public UserPriority(User k) {

switch (k) {

case STUDENT:

priority = 1; break;

case TUTOR:

priority = 3; break;

case INSTRUCTOR:

priority = 7; break;

case DEAN:

priority = 10; break;

default:

priority = 0;

}

}

public int getPriority() {

return priority;

}

}

public class UseEnumMap {

public static void main(String[] args) {

EnumMap<User, UserPriority> faculty =

new EnumMap<User, UserPriority> (User.class);

for (User user : User.values()) {

faculty.put(user,

new UserPriority(user));

}

for (User user : User.values()) {

System.out.println(user.name()

+ "-> Priority:" +

((UserPriority) faculty.get(user)).getPriority());

}

}

}

В результате будет выведено:

STUDENT-> Priority:1

TUTOR-> Priority:3

INSTRUCTOR-> Priority:7

DEAN-> Priority:10

Методы интерфейса NavigableMap<K, V>

Методы данного интерфейса соответствуют методам NavigableSet, но позволяют, кроме того, получать как ключи карты отдельно, так и пары "ключ-значение":

Map.Entry<K,V> lowerEntry(K key);
Map.Entry<K,V> floorEntry(K key);
Map.Entry<K,V> higherEntry(K key);
Map.Entry<K,V> ceilingEntry(K key);
K lowerKey(K key);
K floorKey(K key);
K higherKey(K key);
K ceilingKey(K key);

Методы pollFirstEntry и pollLastEntry возвращают соответственно первый и последний элементы карты, удаляя их из коллекции. Методы firstEntry и lastEntry также возвращают соответствующие элементы, но без удаления.

Map.Entry<K,V> pollFirstEntry();
Map.Entry<K,V> pollLastEntry();
Map.Entry<K,V> firstEntry();
Map.Entry<K,V> lastEntry();

Следующий метод возвращает карту, отсортированную в обратном порядке:
NavigableMap<K,V> descendingMap();

Методы, позволяющие получить набор ключей, отсортированных в прямом и обратном порядке соответственно:

NavigableSet navigableKeySet();
NavigableSet descendingKeySet();

И, наконец, методы, позволяющие извлечь из карты подмножество. Как и в случае NavigableSet, указываем в параметрах начальный и конечный элементы массива ключей, а также необходимость включения в выходной набор граничных элементов. Опять же, если не указывать флаги, то будет использован интервал ключевых значений со включённым начальным элементом, но с исключённым конечным элементом.

NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive);
NavigableMap<K,V> headMap(K toKey, boolean inclusive);
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
SortedMap<K,V> subMap(K fromKey, K toKey);
SortedMap<K,V> headMap(K toKey);
SortedMap<K,V> tailMap(K fromKey);

Унаследованные коллекции

В ряде распределенных приложений, например с использованием сервлетов, до сих пор применяются коллекции, более медленные в обработке, но при этом потокобезопасные, существовавшие в языке Java с момента его создания, а именно карта Hashtable<K,V>, список Vector<E> и перечисление (аналог итератора) Enumeration<E>. Все они также были параметризованы, но сохранили все свои особенности.

КлассHashtable<K,V> реализует интерфейс Map, но обладает также несколькими интересными методами:

Enumeration<V> elements() – возвращает перечисление для значений карты;

Enumeration<K> keys() – возвращает перечисление для ключей карты.

/* пример # 18 : создание хэш-таблицы и поиск элемента по ключу:

HashTableDemo.java */

packageby.bsu.chapt10;

import java.util.*;

import java.io.*;

public class HashTableDemo {

public static void main(String[] args) {

Hashtable<Integer, Double> ht =

new Hashtable<Integer, Double>();

for (int i = 0; i < 5; i++) {

ht.put(i, Math.atan(i));

}

Enumeration<Integer> ek = ht.keys();

int key;

while (ek.hasMoreElements()) {

key = ek.nextElement();

System.out.printf("%4d ", key);

}

System.out.println("");

Enumeration<Double> ev = ht.elements();

double value;

while (ev.hasMoreElements()) {

value = ev.nextElement();

System.out.printf("%.2f ", value);

}

}

}

В результате в консоль будет выведено:

4 3 2 1 0

1,33 1,25 1,11 0,79 0,00

Принципы работы с коллекциями, в отличие от их структуры, со сменой версий языка существенно не изменились.

Класс Collections

Класс Collections содержит большое количество статических методов, предназначенных для манипулирования коллекциями.С применением предыдущих версий языка было разработано множество коллекций, в которых никаких проверок нет, следовательно, при их использовании нельзя гарантировать, что в коллекцию не будет помещен “посторонний” объект. Для этого в класс Collections был добавлен новый метод:public static <E> Collection <E> checkedCollection(Collection<E> c, Class<E> type)

Этот метод создает коллекцию, проверяемую на этапе выполнения, то есть
в случае добавления “постороннего” объекта генерируется исключение ClassCastException:

/* # 19 : проверяемая коллекция: SafeSet.java */

packageby.bsu.chapt10;

import java.util.*;

public class SafeSet {

public static void main(String args[]) {

//HashSet c = new HashSet();

HashSet c = Collections.checkedSet(

new HashSet<String>(), String.class);

c.add("Java");

c.add(7.0); // ошибка времени выполнения

}

}

В этот же класс добавлен целый ряд статических методов, специализированных для проверки конкретных типов коллекций, а именно: checkedList(),
checkedSortedMap(), checkedMap(), checkedSortedSet(),
checkedCollection(), а также:

<T> boolean addAll(Collection<? super T> c, T... a) – добавляет в параметризованную коллекцию соответствующие параметризации элементы;

<T> void copy(List<? super T> dest, List<? extends T> src) – копирует все элементы из одного списка в другой;

boolean disjoint(Collection<?> c1, Collection<?> c2) – возвращает true, если коллекции не содержат одинаковых элементов;

<T> List <T> emptyList(), <K,V> Map <K,V> emptyMap(),
<T> Set <T> emptySet()
– возвращают пустой список, карту отображения
и множество соответственно;

<T> void fill(List<? super T> list, T obj) – заполняет список заданным элементом ;

int frequency(Collection<?> c, Object o) – возвращает количество вхождений в коллекцию заданного элемента;

<T extends Object & Comparable <? super T>> T max(Collection<? extends T> coll),

<T extends Object & Comparable <? super T>> T min(Collection<? extends T> coll)– возвращают минимальный
и максимальный элемент соответственно;

<T> T max(Collection <? extends T> coll,

Comparator<? super T> comp),

<T> T min(Collection<? extends T> coll,

Comparator<? super T> comp) – возвращают минимальный и максимальный элемент соответственно, используя Comparator для сравнения;

<T> List <T> nCopies(int n, T o) – возвращает список из nзаданных элементов;

<T> boolean replaceAll(List<T> list, T oldVal, T newVal) – заменяет все заданные элементы новыми;

void reverse(List<?> list) – “переворачивает” список;

void rotate(List<?> list, int distance) – сдвигает список циклически на заданное число элементов;

void shuffle(List<?> list) – перетасовывает элементы списка;

<T> Set <T> singleton(T o), singletonList(T o), singletonMap(K key, V value) – создают множество, список и карту отображения, состоящие из одного элемента;

<T extends Comparable<? super T>> void sort(List<T> list),

<T> void sort(List<T> list, Comparator<? super T> c) – сортировка списка, естественным порядком и используя Comparator соответственно;

void swap(List<?> list, int i, int j) – меняет местами элементы списка стоящие на заданных позициях.

/* # 20 : методы класса Collections: CollectionsDemo.java:

MyComparator.java */

package by.bsu.chapt10;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class CollectionsDemo {

public static void main(String[] args) {

MyComparator<Integer> comp =

new MyComparator<Integer>();

ArrayList<Integer> list =

new ArrayList<Integer>();

Collections.addAll(list, 1, 2, 3, 4, 5);

Collections.shuffle(list);

print(list);

Collections.sort(list, comp);

print(list);

Collections.reverse(list);

print(list);

Collections.rotate(list, 3);

print(list);

System.out.println("min: "

+ Collections.min(list, comp));

System.out.println("max: "

+ Collections.max(list, comp));

List<Integer> singl =

Collections.singletonList(71);

print(singl);

//singl.add(21);//ошибка времени выполнения

}

static void print(List<Integer> c) {

for (int i : c)

System.out.print(i + " ");

System.out.println();

}

}

package chapt10;

import java.util.Comparator;

public class MyComparator<T> implements Comparator<Integer> {

public int compare(Integer n, Integer m) {

return m.intValue() - n.intValue();

}

}

В результате будет выведено:

4 3 5 1 2

5 4 3 2 1

1 2 3 4 5

3 4 5 1 2

min: 5

max: 1

Класс Arrays

В пакете java.util находится класс Arrays, который содержит методы манипулирования содержимым массива, а именно для поиска, заполнения, сравнения, преобразования в коллекцию и прочие:

static int binarySearch(параметры) – перегруженный метод организации бинарного поиска значения в массивах примитивных и объектных типов. Возвращает позицию первого совпадения;

static void fill(параметры) – перегруженный метод для заполнения массивов значениями различных типов и примитивами;

static void sort(параметры) – перегруженный метод сортировки массива или его части с использованием интерфейса Comparator и без него;

static <T> T[] copyOf(T[] original, int newLength) –заполняет массив определенной длины, отбрасывая элементы или заполняя null при необходимости;

static <T> T[] copyOfRange(T[] original, int from, int to) – копирует заданную область массива в новый массив;

static boolean equals(массив1, массив2) – перегруженный метод сравнения массивов;

static boolean deepEquals(Object[] a1, Object[] a2) –“глубокое” сравнение массивов;

static String deepToString(Object[] a) – “глубокое” преобразование массива в строку;

static int deepHashCode(Object[] a) – вычисление хэш-кода исходя из значений элементов массива;

static <T> List<T> asList(T... a) – метод, копирующий элементы массива в объект типа List<T>.

В качестве простого примера применения указанных методов можно привести следующий код.

/* пример # 21 : методы класса Arrays : ArraysEqualDemo.java */

packagechapt10;

import java.util.*;

public class ArraysEqualDemo {

public static void main(String[] args) {

char m1[] = new char[3];

charm2[] = { 'a', 'b', 'c' };

chari;

Arrays.fill(m1, 'a');

System.out.print("массив m1:");

for (i = 0; i < 3; i++) {

System.out.print(" " + m1[i]);

}

m1[1] = 'b';

m1[2] = 'c';

//m1[2]='x'; // приведет к другому результату

if (Arrays.equals(m1, m2))

System.out.print("\nm1 и m2 эквивалентны");

Else

System.out.print("\nm1 и m2 не эквивалентны");

m1[0] = 'z';

Arrays.sort(m1);

System.out.print("\nмассив m1:");

for (i = 0; i < 3; i++)

System.out.print(" " + m1[i]);

System.out.print(

"\n значение 'c' находится в позиции-"

+ Arrays.binarySearch(m1, 'c'));

Integer arr[] = {35, 71, 92};

//вывод массива объектов в строку

System.out.println(Arrays.deepToString(arr));

//вычисление хэш-кода исходя и значений элементов

System.out.println(Arrays.deepHashCode(arr));

Integer arr2[] = {35, 71, 92};

//сравнение массивов по седержимому

System.out.println(Arrays.deepEquals(arr, arr2));

char m3[] = new char[5];

// копирование массива

m3 = Arrays.copyOf(m1, 5);

System.out.print("массив m3:");

for (i = 0; i < 5; i++) {

System.out.print(" " + m3[i]);

}

}

}

В результате компиляции и запуска будет выведено:

массив m1: a a a

M1 и m2 эквивалентны

массив m1: b c z

значение 'c' находится в позиции 1

[35, 71, 92]

True

массив m3: b c z □ □

Наши рекомендации