Лекция 13 JavaBeans С точки зрения ООП, компонент JavaBean – это классический самодостаточный объект, который, будучи написан один раз, может быть многократно.

Презентация:



Advertisements
Похожие презентации
1 Java 10. КОЛЛЕКЦИИ Множества Карты отображений.
Advertisements

1 Java 10. КОЛЛЕКЦИИ Основные концепции. Интерфейсы. Списки.
Коллекции классов Лекция 12. С помощью коллекций вместо создания структур данных программист использует готовые структуры данных, не заботясь об их реализации.
САОД кафедра ОСУ 1 Основные абстрактные типы данных Схема процесса создания программ для решения прикладных задач ВУ.
Collections Framework Java Advanced. 2Georgiy KorneevJava Advanced / Collections Framework Содержание 1.Коллекции 2.Множества 3.Списки 4.Очереди 5.Отображения.
Java : массивы и коллекции. Массивы Массивы простых типов: int []a = new int[10]; int []b = new int[]{ 0, 1, 2, 3, 4, 5 }; Массивы ссылочных типов (reference.
Ассоциативные списки Поиск данных происходит не по индексу или положению объекта, а по его ассоциативной связи: public interface Map { // Доступ к объектам.
1 Параметризация типов в Java public class Box { private Object object; public void add(Object object) { this.object = object; } public Object get() {
Контейнеры Сортировка Метод sort() Интерфейс Comparable метод int compareTo(Object o) вызов: Arrays.sort(a) Интерфейс Comparator метод int compare(Object.
Collections Framework Java Advanced. 2Georgiy KorneevJava Advanced / Collections Framework Содержание 1.Коллекции 2.Множества 3.Списки 4.Очереди и деки.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
АССОЦИАТИВНЫЕ КОЛЛЕКЦИИ Лекция 6 1. Отличие от последовательных 2 В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Абстрактный тип данных список. Операции над абстрактным списком Создать пустой список Уничтожить список Определить, пуст ли список Определить количество.
Изучение динамического определения типов. Класс Class. Динамическая загрузка и инстанцирование классов. В Java вся информация о классе хранится в специальном.
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Лекция 2 Наследование Наследование в Java имеет тот же смысл, что и в С++. Однако наследование в Java осуществляется при помощи ключевого слова extends.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
Основы ООП и C# Работа с объектами и классами. Классы Класс специальный тип данных для описания объектов. Он определяет данные и поведение типа. Определение.
Транксрипт:

Лекция 13

JavaBeans С точки зрения ООП, компонент JavaBean – это классический самодостаточный объект, который, будучи написан один раз, может быть многократно использован при построении новых апплетов, сервлетов, полноценных приложений, а также других компонентов JavaBean. Отличие от других технологий заключается в том, что компонент JavaBean (или просто Bean) строится по определенным правилам, с использованием в некоторых ситуациях строго регламентированных интерфейсов и базовых классов.

Преимуществом от использования технологии JavaBean является возможность визуальной сборки приложений из готовых компонентов Bean. В идеале, от разработчика приложения может даже не потребоваться непосредственного написания программного кода. В основе указанной технологии визуального построения приложений лежит механизм анализа - introspection, позволяющий производить анализ компонент Bean, предоставленных сторонними разработчиками, автоматически определяя их атрибуты, методы и обрабатываемые события. Использование такого механизма подразумевает следование определенным правилам при именовании свойств и выборе методов, а также явное декларирование свойств, методов и событий в специальном классе реализующем интерфейс BeanInfo.

Другая составляющая технологии JavaBean – событийная (event) модель взаимодействия между компонентами Bean. Стандартный API JavaBean предусматривает вполне определенный интерфейс для компонентов Bean, ждущих возникновения событий (получения объектов java.util.EventObject), а также их обязательную регистрацию в компонентах Bean, которые эти события инициируют. Компоненты Beans должны реализовывать интерфейс Serializable.

Свойства компоненты Bean – это именованные атрибуты соответствующего объекта, которые могут оказывать влияние на режим его функционирования. В отличие от атрибутов обычного класса, свойства компоненты Bean должны задаваться вполне определенным образом: нежелательно объявлять какой-либо атрибут компоненты Bean как public. Атрибут следует декларировать как private, а сам класс дополнить двумя методами set и get.

Например: private Myclass m_class; public void setMyclass(Myclass newMyclass) {m_class = newMyclass; } public Myclass getMyclass() { return m_class; } Следует заметить, что согласно спецификации Bean, аналогичные методы set и get необходимо использовать не только для атрибутов простого типа, таких как int или String, но и в более сложных ситуациях, например для внутренних массивов String[].

Атрибуту типа boolean в классе Bean должны соответствовать несколько иные методы: is и set. Например: private boolean m_Ready; public void setReady(boolean newStatus) { m_Ready = newStatus; } public boolean isReady() { return m_Ready; } Следует заметить, что реализуя тот или иной метод, необходимо учитывать, что создаваемый компонент Bean должен будет функционировать в программной среде со многими параллельными потоками, т.е. в условиях, когда сразу от нескольких потоков могут поступить запросы на доступ к тем или иным методам или атрибутам объекта.

События в модели JavaBean Одной из составляющих технологии JavaBean является событийная модель взаимодействия компонентов приложения. Согласно концепции, события – это механизм рассылки уведомлений об изменении состояния некого исходного объекта, которые передаются одному или нескольким объектам-адресатам. Каждый экземпляр класса, ждущий появления какого-либо события, должен соответствующим образом зарегистрироваться и также реализовать интерфейс EventListener. Информация о смене состояния заключается в специально созданный для этого объект, который наследуется от java.util.EventObject и передается объекту-адресату как аргумент соответствующего метода.

Уведомление об изменении значения контролируемого свойства Bean При реализации приложения может понадобиться, чтобы когда в экземпляре Bean меняется значение какого-либо атрибута, соответствующая информация автоматически передавалась другим компонентам приложения, чтобы те имели возможность отреагировать соответствующим образом. Класс Bean, содержащий контролируемый атрибут, должен иметь у себя список контролирующих его объектов (listeners), а также иметь public методы, позволяющие таким объектам добавлять себя в этот список, либо, наоборот, изымать себя из него. И упомянутый список, и методы реализованы в классе PropertyChangeSupport.

Рассмотрим пример: import java.beans.*; import java.io.*; class Controlledclass{ private Integer status;//контролируемое свойство private PropertyChangeSupport changes = new PropertyChangeSupport(this); public Controlledclass(){ status=new Integer(0);} public void setStatus(int s){ Integer oldstatus=new Integer(status.intValue()); status=new Integer(s); changes.firePropertyChange("status", oldstatus, status);}

public int getStatus(){return status;} public void addPropertyChangeListener (PropertyChangeListener l){ changes.addPropertyChangeListener(l);} public void removePropertyChangeListener (PropertyChangeListener l){ changes.removePropertyChangeListener(l); } }

//Уведомляемый класс class Noticedclass implements PropertyChangeListener,Serializable { private String str; public void setStr(String s){str=s; } public String getStr(){return str;} public void propertyChange(PropertyChangeEvent e){ System.out.println("Change status");} }

public class JavaApplication1 { public static void main(String[] args) { Controlledclass mc1=new Controlledclass (); Noticedclass mc=new Noticedclass(); mc1.addPropertyChangeListener(mc); System.out.println(mc1.getStatus()); mc1.setStatus(10); }} На экране получим: 0 Change status

Контроль над свойством другого объекта Bean с правом вето Допустим, необходимо, как и в предыдущем примере, реализовать классы Controlledclass и Noticedclass. Однако требуется, чтобы объект Noticedclass мог давать разрешение на изменение атрибута status в объекте класса Controlledclass. Чтобы это стало возможным, необходимо, в объекте класса Controlledclass создать объект vetoes – экземпляр класса VetoableChangeSupport, который будет содержать список объектов, уведомляемых о предполагаемом изменении значения атрибута. Рассмотрим пример:

import java.beans.*; import java.io.*; class Controlledclass { private Integer status; private VetoableChangeSupport vetos = new VetoableChangeSupport(this); public Controlledclass(){status=new Integer(0);} public void setStatus(int s)throws PropertyVetoException { Integer oldstatus=new Integer(status.intValue()); vetos.fireVetoableChange("status", oldstatus, new Integer(s)); status=new Integer(s); }

public int getStatus(){return status;} public void addVetoableChangeListener (VetoableChangeListener l){ vetos.addVetoableChangeListener(l);} public void removeVetoableChangeListener (VetoableChangeListener l){ vetos.removeVetoableChangeListener(l);} }

class Noticedclass implements VetoableChangeListener,Serializable { private String str; public void setStr(String s){str=s; } public String getStr(){return str;} public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException{ Integer newval=(Integer)e.getNewValue(); if (newval.intValue()==10){ throw new PropertyVetoException("Error",e);} }}

public class Main { public static void main(String[] args) { try{ Controlledclass mc1=new Controlledclass (); Noticedclass mc=new Noticedclass(); mc1.addVetoableChangeListener(mc); System.out.println(mc1.getStatus()); mc1.setStatus(10);} catch(PropertyVetoException e) {System.out.println("Error"); } } } На экране получим: 0 Error

Дескрипторы компонентов Bean и методика Customization Если программный модуль реализуется в виде набора компонент Bean, спецификация рекомендует, чтобы его разработчик в отдельном классе, реализующем интерфейс BeanInfo, стандартным образом описал все методы и атрибуты, которые должны быть доступны разработчику, использующему этот модуль для построения конечного приложения. Те параметры, которые используются для внутренних целей, разработчик компоненты Bean в этом классе может просто игнорировать. Использование стандартного механизма, позволяющего автоматически получить информацию об интерфейсе компонента Bean, разработанного сторонней компанией, позволяет представить компоненты, из которых строится конечное приложение, и их интерфейс в визуальной форме.

Фактически это означает, что разработчик получает возможность визуальным образом создавать специальный класс, который образует надстройку над используемыми компонентами Bean, реализуя при этом логику конечного приложения. Сама описываемая процедура называется customization. С другой стороны, разработчик компоненты Bean может взять в свои руки разработку программного модуля, позволяющего выполнять ее дополнительную настройку: редактор свойств. Спецификация JavaBean требует, чтобы класс, который соответствует подобному редактору свойств, реализовывал интерфейс PropertyEditor.

Соответственно, любой компонент Bean в программном модуле, передаваемом разработчику конечного приложения, может сопровождать специальный класс Customizer, который управляет его настройкой. При этом сам класс Customizer должен либо непосредственно, либо косвенно наследовать класс java.awt.Component или же реализовывать интерфейс java.beans.Customizer.

Реализация интерфейса BeanInfo Интерфейс BeanInfo не играет значимой роли в функционировании конечного приложения. Его задача – предоставлять разработчикам бизнес-приложения информацию о тех или иных параметрах компонента Bean ровно в той мере, насколько это необходимо для его использования. Интерфейс BeanInfo предусматривает реализацию методов, возвращающих описания свойств, методов и событий, которые обрабатываются данным Bean и должны быть предоставлены разработчику приложения:

PropertyDescriptor[] getPropertyDescriptors(); MethodDescriptor[] getMethodDescriptors(); EventSetDescriptior[] getEventSetDescriptiors(); Все три типа дескрипторов – PropertyDescriptor, MethodDescriptor и EventSetDescriptior - являются потомками общего класса FeatureDescriptor, обеспечивающего предоставление самой общей информации о тех или иных свойствах компоненты Bean.

Рассмотрим пример. Рассмотрим класс бина: import java.io.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; public class Main extends JPanel implements Serializable { private JSlider slider; private JTextField field; private Box boxContainer; private int currentValue; private PropertyChangeSupport changeSupport;

public Main(){ changeSupport=new PropertyChangeSupport(this); //инициализация ползунка slider= new JSlider(SwingConstants.HORIZONTAL,1,100,1); field= new JTextField(String.valueOf(slider.getValue()),5); boxContainer=new Box(BoxLayout.X_AXIS); boxContainer.add(slider); boxContainer.add(Box.createHorizontalStrut(5)); boxContainer.add(field); setLayout(new BorderLayout()); add(boxContainer);

//добавление слушателя ChangeListener для JSlider ChangeListener l=new ChangeListener(){ public void stateChanged(ChangeEvent e){ setCurrentValue(slider.getValue());}}; slider.addChangeListener(l); ActionListener l1=new ActionListener(){ public void actionPerformed(ActionEvent e){ setCurrentValue(Integer.parseInt(field.getText())); } }; field.addActionListener(l1); } public void addPropertyChangeListener(PropertyChangeListener listn){ changeSupport.addPropertyChangeListener(listn); }

public void removePropertyChangeListener (PropertyChangeListener listn){ changeSupport.removePropertyChangeListener(listn); } public void setMinimumValue(int min){ slider.setMinimum(min); if(slider.getValue()

public void setMaximumValue(int max){ slider.setMaximum(max); if(slider.getValue()>slider.getMaximum()){ slider.setValue(slider.getMaximum()); field.setText(String.valueOf(slider.getValue())); } }; public int getMaximumValue(){return slider.getMaximum();} public void setCurrentValue(int cur) throws IllegalArgumentException{ if(cur

public int getCurrentValue(){return slider.getValue();} public void setFieldWidth(int col){ field.setColumns(col); boxContainer.validate(); } public int getFieldWidth(){ return field.getColumns();} public Dimension getMimimumSize(){ return boxContainer.getMinimumSize();} public Dimension getPrefferedSize(){ return boxContainer.getPreferredSize();}

Класс MainBeanInfo.java import java.beans.*; import javax.swing.*; public class MainBeanInfo extends SimpleBeanInfo{ public static final Class beanClass=Main.class; //возврат общего описания bean компонента public BeanDescriptor getBeanDescriptor(){ BeanDescriptor descriptor=new BeanDescriptor(beanClass,PanelCustomizer.class); descriptor.setDisplayName("Slider Panel"); return descriptor; }

//возврат массива дескрипторов MethodDescriptor для открытых методов get класса Main public MethodDescriptor[] getMethodDescriptors(){ try{ MethodDescriptor getMinimumValue=new MethodDescriptor(beanClass.getMethod ("getMinimumValue", null)); MethodDescriptor getMaximumValue=new MethodDescriptor(beanClass.getMethod ("getMaximumValue",null)); MethodDescriptor getCurrentValue=new MethodDescriptor(beanClass.getMethod ("getCurrentValue", null)); MethodDescriptor getFieldWidth=new MethodDescriptor(beanClass.getMethod ("getFieldWidth", null));

MethodDescriptor[] descriptors={getMinimumValue, getMaximumValue,getCurrentValue, getFieldWidth}; return descriptors;} catch(NoSuchMethodException sm) {sm.printStackTrace();} catch(SecurityException e) {e.printStackTrace();} return null;}

public PropertyDescriptor[] getPropertyDescriptors()throws RuntimeException{ try{ PropertyDescriptor fieldWidth=new PropertyDescriptor("fieldWidth",beanClass); PropertyDescriptor currentValue=new PropertyDescriptor("currentValue",beanClass); PropertyDescriptor maximumValue=new PropertyDescriptor("maximumValue",beanClass); maximumValue.setPropertyEditorClass(MaximumValueEditor.class); PropertyDescriptor minimumValue=new PropertyDescriptor("minimumValue",beanClass); minimumValue.setPropertyEditorClass(MinimumValueEditor.class);

//убедиться, что имело место событие PropertyChangeEvent для этого свойсва currentValue.setBound(true); PropertyDescriptor descriptors[]={fieldWidth,currentValue, maximumValue,minimumValue}; return descriptors; } catch(IntrospectionException e){ throw new RuntimeException(e.getMessage());} }

public int getDefaultPropertyIndex(){return 1;} public EventSetDescriptor[] getEventSetDescriptors() throws RuntimeException { try{ //последний параметр - имя метода, в данном случае метод реализованный в классе; второй параметр–название события PropertyChangeListener EventSetDescriptor changed=new EventSetDescriptor(beanClass,"propertyChange", PropertyChangeListener.class,"propertyChange"); changed.setDisplayName("Main Panel changed"); EventSetDescriptor[] descriptors={changed}; return descriptors; } catch(IntrospectionException e){ throw new RuntimeException(e.getMessage());} } public int getDefaultEventIndex(){return 0;}}

Класс PanelCustomizer.java import java.io.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; public class PanelCustomizer extends JPanel implements Customizer{ private JComboBox maximumCombo, minimumCombo; private JLabel minimumLabel,maximumLabel; protected Main slider; private PropertyChangeSupport changeSupport; private static final String[] VALUES={"50","100","150","200","250","300","500"};

public PanelCustomizer(){ changeSupport=new PropertyChangeSupport(this); minimumLabel=new JLabel("Minimum Value"); maximumLabel=new JLabel("Maximum value"); maximumCombo=new JComboBox(VALUES); maximumCombo.setSelectedIndex(0); minimumCombo=new JComboBox(VALUES); minimumCombo.setSelectedIndex(0);

ActionListener l=new ActionListener() { public void actionPerformed(ActionEvent e){ setMinimum(minimumCombo.getSelectedIndex());} }; minimumCombo.addActionListener(l); ActionListener l1=new ActionListener() { public void actionPerformed(ActionEvent e){ setMaximum(maximumCombo.getSelectedIndex());} }; maximumCombo.addActionListener(l1); add(minimumLabel); add(minimumCombo); add(maximumLabel); add(maximumCombo); }

public void setObject(Object bean){slider=(Main)bean;} public void addPropertyChangeListener(PropertyChangeListener listn){ changeSupport.addPropertyChangeListener(listn); } public void removePropertyChangeListener(PropertyChangeListener listn){ changeSupport.removePropertyChangeListener(listn); } public void setMinimum(int index){ int oldValue=slider.getMinimumValue(); int newValue=Integer.parseInt(VALUES[index]); slider.setMinimumValue(newValue); changeSupport.firePropertyChange("minimumValue", new Integer(oldValue),new Integer(newValue)); }

public void setMaximum(int index){ int oldValue=slider.getMinimumValue(); int newValue=Integer.parseInt(VALUES[index]); slider.setMinimumValue(newValue); changeSupport.firePropertyChange( "maximumValue",new Integer(oldValue), new Integer(newValue));} }

Редакторы свойств имеют вид: Класс MaximumValueEditor.java import java.beans.*; public class MaximumValueEditor extends PropertyEditorSupport{ private Integer maximumValue; public void setValue(Object value){ maximumValue=(Integer)value; firePropertyChange(); }; public Object getValue(){ return maximumValue;};

//Задание свойства maximumValue из текстовой строки public void setAsText(String str){ try{ maximumValue=Integer.decode(str); firePropertyChange(); } catch(NumberFormatException e){ throw new IllegalArgumentException();} } //получение строкового массива для ниспадающего меню public String[] getTags(){ return new String[]{"50","100","150","200","250","300","500"}; } public String getAsText(){return getValue().toString();} public String getInitializationString(){return getValue().toString();}}

Файл MinimumValueEditor.java import java.beans.*; public class MinimumValueEditor extends PropertyEditorSupport{ private Integer minimumValue; public void setValue(Object value){ minimumValue=(Integer)value; firePropertyChange(); }; public Object getValue(){ return minimumValue;};

//Задание свойства maximumValue из текстовой строки public void setAsText(String str){ try{ minimumValue=Integer.decode(str); firePropertyChange(); } catch(NumberFormatException e) { throw new IllegalArgumentException();} } //получение строкового массива для ниспадающего меню public String[] getTags(){ return new String[]{"50","100","150","200","250","300","500"}; } public String getAsText(){return getValue().toString();} public String getInitializationString(){return getValue().toString();} }

Коллекции Коллекции – это хранилища, поддерживающие различные способы накопления и упорядочения объектов с целью обеспечения возможностей эффективного доступа к ним. Они представляют собой реализацию абстрактных типов (структур) данных, поддерживающих три основные операции: добавление нового элемента в коллекцию; удаление элемента из коллекции; изменение элемента в коллекции.

Коллекции в языке Java объединены в библиотеке классов java.util и представляют собой контейнеры для хранения и манипулирования объектами. До появления Java 2 эта библиотека содержала классы только для работы с простейшими структурами данных: Vector, Stack, Hashtable, BitSet, а также интерфейс Enumeration для работы с элементами этих классов. Коллекции, появившиеся в Java 2, представляют общую технологию хранения и доступа к объектам.

Начиная с версии 5.0 коллекции стали типизированными. Интерфейсы коллекций: Map – карта отображения вида ключ- значение; Collection – вершина иерархии остальных коллекций; List – специализирует коллекции для обработки списков; Set – специализирует коллекции для обработки множеств, содержащих уникальные элементы. Все классы коллекций реализуют также интерфейсы Serializable, Cloneable (кроме WeakHashMap). Кроме того, классы, реализующие интерфейсы List и Set, реализуют также интерфейс Iterable.

В интерфейсе Collection определены методы, которые работают на всех коллекциях: boolean add(E obj) – добавляет obj к вызывающей коллекции и возвращает true, если объект добавлен, и false, если obj уже элемент коллекции; boolean addAll(Collection c) – добавляет все элементы коллекции к вызывающей коллекции; void clear() – удаляет все элементы из коллекции; boolean contains(Object obj) – возвращает true, если вызывающая коллекция содержит элемент obj; boolean equals(Object obj) – возвращает true, если соответствующие элементы коллекции эквивалентны; boolean isEmpty() – возвращает true, если коллекция пуста; Iterator iterator() – извлекает итератор; boolean remove(Object obj) – удаляет obj из коллекции; int size() – возвращает количество элементов в коллекции; Object[ ] toArray() – копирует элементы коллекции в массив объектов; T [ ] toArray(T a[ ]) – копирует элементы коллекции в массив объектов определенного типа.

Для работы с элементами коллекции применяются следующие интерфейсы: Comparator – для сравнения объектов; Iterator, ListIterator, Map.Entry – для перечисления и доступа к объектам коллекции. Методы интерфейса Iterator : boolean hasNext() – проверяет наличие следующего элемента, а в случае его отсутствия (завершения коллекции) возвращает false. Итератор при этом остается неизменным; E next() – возвращает объект, на который указывает итератор, и передвигает текущий указатель на следующий, предоставляя доступ к следующему элементу. Если следующий элемент коллекции отсутствует, то метод next() генерирует исключение NoSuchElementException; void remove() – удаляет объект, возвращенный последним вызовом метода next().

Интерфейс ListIterator расширяет интерфейс Iterator и предназначен в основном для работы со списками. Наличие методов E previous(), int previousIndex() и boolean hasPrevious() обеспечивает обратную навигацию по списку. Метод int nextIndex() возвращает номер элемента, на котором будет находиться итератор после вызова метода next(). Метод void add(E obj) позволяет вставлять элемент в список текущей позиции. Вызов метода void set(E obj) производит замену текущего элемента списка на объект, передаваемый методу в качестве параметра.

Интерфейс Map.Entry предназначен для извлечения ключей и значений карты с помощью методов K getKey() и V getValue() соответственно. Вызов метода V setValue(V value) заменяет значение, ассоциированное с текущим ключом. Класс ArrayList – динамический массив объектных ссылок. Расширяет класс AbstractList и реализует интерфейс List. Класс имеет конструкторы: ArrayList() ArrayList(Collection c) ArrayList(int capacity)

Методы интерфейса List позволяют вставлять и удалять элементы из позиций, указываемых через отсчитываемый от нуля индекс: void add(int index, E element) – вставляет element в позицию, указанную в index; void addAll(int index, Collection c) – вставляет в вызывающий список все элементы коллекции с, начиная с позиции index; E get(int index) – возвращает элемент в виде объекта из позиции index; int indexOf(Object ob) – возвращает индекс указанного объекта; E remove(int index) – удаляет объект из позиции index; E set(int index, E element) – заменяет объект в позиции index, возвращает при этом удаляемый элемент; List subList(int fromIndex, int toIndex) – извлекает часть коллекции в указанных границах

Рассмотрим пример: import java.util.*; public class DemoGeneric { public static void main(String args[]) { ArrayList list = new ArrayList (); list.add("Java"); list.add("Fortress"); String res = list.get(0);/* компилятор знает тип значения */ list.add(new StringBuilder("C#")); // ошибка компиляции, компилятор не позволит добавить посторонний тип System.out.print(list);}}

Пример. Неккоректная коллекция. import java.util.*; public class UncheckCheck { public static void main(String args[ ]) { ArrayList list = new ArrayList(); list.add(71); list.add(new Boolean(true")); list.add("Java 1.6.0"); // требуется приведение типов int i = (Integer)list.get(0); boolean b = (Boolean)list.get(1); String str = (String)list.get(2); for (Object ob : list){ System.out.println("list " + ob);}

ArrayList s = new ArrayList (); s.add(71); s.add(92); s.add("101"); //ошибка компиляции for (Integer ob : s){ System.out.print("int " + ob);} }

Пример. Использование Iterator. import java.util.*; public class DemoIterator { public static void main(String[ ] args) { ArrayList c =new ArrayList (7); for(int i = 0 ;i < 10; i++) { double z = new Random().nextGaussian(); c.add(z);} for(Double d: c) { System.out.printf("%.2f ",d);} int positiveNum = 0; int size = c.size();//определение размера коллекции

//извлечение итератора Iterator it = c.iterator(); while(it.hasNext()) { if (it.next() > 0){ positiveNum++; } else { it.remove();} } System.out.printf("%n Количество положительных: %d ", positiveNum); System.out.printf("%n Количество неположительных: %d ", size - positiveNum); System.out.println("\n Положительная коллекция"); for(Double d : c) { System.out.printf("%.2f ",d);}}}

Класс LinkedList реализует интерфейс Queue. Методы интерфейса Queue : E element() – возвращает, но не удаляет головной элемент очереди; boolean offer(E o) – вставляет элемент в очередь, если возможно; E peek() – возвращает, но не удаляет головной элемент очереди, возвращает null, если очередь пуста; E poll() – возвращает и удаляет головной элемент очереди, возвращает null, если очередь пуста; E remove() – возвращает и удаляет головной элемент очереди. Методы element() и remove() отличаются от методов peek() и poll() тем, что генерируют исключение, если очередь пуста.

Пример. import java.util.*; public class DemoLinkedList { public static void main(String[] args){ LinkedList a = new LinkedList (); for(int i = 10; i

while(list.hasPrevious()) System.out.print(list.previous()+" "); a.removeFirst(); a.offer(71); // добавление элемента в конец списка a.poll(); // удаление нулевого элемента из списка a.remove(); // удаление нулевого элемента из списка a.remove(1); // удаление первого элемента из списка System.out.println("\n" + a); Queue q = a; // список в очередь for (Number i : q){ System.out.print(i + " "); } System.out.println(" :size= " + q.size()); for (int i = 0; i < 5; i++) { Number res = q.poll(); } System.out.print("size= " + q.size());} }

При реализации интерфейса Comparator существует возможность сортировки списка объектов конкретного типа по правилам, определенным для этого типа. Для этого необходимо реализовать метод int compare(T ob1, T ob2), принимающий в качестве параметров два объекта для которых должно быть определено возвращаемое целое значение, знак которого и определяет правило сортировки. Этот метод автоматически вызывается методом public static void sort(List list, Comparator c) класса Collections, в качестве первого параметра принимающий коллекцию, в качестве второго – объект-comparator, из которого извлекается правило сортировки.

Пример. import java.util.Comparator; public class Student implements Comparator { private int idStudent; private float meanMark; public Student(float m, int id) { meanMark = m; idStudent = id;} public Student() { } public float getMark() {return meanMark;} public int getIdStudent() {return idStudent;} // правило сортировки public int compare(Student one, Student two) { return (int)(Math.ceil(two.getMark() - one.getMark()));} }

import java.util.*; public class UniqSortMark { public static void main(String[] args) { ArrayList p = new ArrayList (); p.add(new Student(3.9f, 52201)); p.add(new Student(3.65f, 52214)); p.add(new Student(3.71f, 52251)); p.add(new Student(3.02f, 52277)); p.add(new Student(3.81f, 52292)); p.add(new Student(9.55f, 52271)); // сортировка списка объектов try { Collections.sort(p, Student.class.newInstance()); } catch (InstantiationException e1) { //невозможно создать объект класса e1.printStackTrace(); } catch (IllegalAccessException e2) { e2.printStackTrace();} for (Student ob : p) System.out.printf("%.2f ", ob.getMark()); }}

Множества Интерфейс Set объявляет поведение коллекции, не допускающей дублирования элементов. Интерфейс SortedSet наследует Set и объявляет поведение набора, отсортированного в возрастающем порядке, заранее определенном для класса. Интерфейс NavigableSet облегчает поиск элементов.

Класс HashSet наследуется от абстрактного суперкласса AbstractSet и реализует интерфейс Set, используя хэш-таблицу для хранения коллекции. Ключ (хэш-код) используется вместо индекса для доступа к данным, что значительно ускоряет поиск определенного элемента. Конструкторы класса: HashSet() HashSet(Collection c) HashSet(int capacity) HashSet(int capacity, float loadFactor), где capacity – число ячеек для хранения хэш-кодов; loadFactor -процент заполненности буфера, по достижении которого увеличивается его размер(по умолчанию 0.75).

Пример. import java.util.*; import java.io.*; public class DemoHashSet { public static void main(String[] args) { HashSet words = new HashSet (100); // использовать коллекции LinkedHashSet или TreeSet long callTime = System.nanoTime(); try { BufferedReader in =new BufferedReader( new FileReader("c://aaa.txt")); String line = ""; while ((line = in.readLine()) != null) { StringTokenizer tokenizer =new StringTokenizer(line, "(){}[]#*!?.,:;-\'\"/"); while (tokenizer.hasMoreTokens()) { String word = tokenizer.nextToken(); words.add(word.toLowerCase());}}} catch (IOException e) {System.err.println(e);}

Iterator it = words.iterator(); while (it.hasNext()){ System.out.println(it.next());} long totalTime = System.nanoTime()- callTime; System.out.println("различных слов: " + words.size()+ ", " + totalTime + наносекунд");} }

Класс TreeSet для хранения объектов использует бинарное дерево. При добавлении объекта в дерево он сразу же размещается в необходимую позицию с учетом сортировки. Сортировка происходит благодаря тому, что все добавляемые элементы реализуют интерфейсы Comparator и Comparable. Конструкторы класса: TreeSet() TreeSet(Collection c) TreeSet(Comparator c) TreeSet(SortedSet s)

Класс TreeSet содержит методы по извлечению первого и последнего (наименьшего и наибольшего) элементов E first() и E last(). Методы SortedSet subSet(E from, E to), SortedSet tailSet(E from) и SortedSet headSet(E to) предназначены для извлечения определенной части множества. Метод Comparator comparator() возвращает объект Comparator, используемый для сортировки объектов множества или null, если выполняется обычная сортировка.

Пример. import java.util.*; public class DemoTreeSet { public static void main(String[] args) { ArrayList c = new ArrayList (); boolean b; for (int i = 0; i < 6; i++){ c.add((int) (Math.random() * 71) + "Y");} System.out.println(c + "список"); TreeSet set = new TreeSet (c); System.out.println(set + "множество"); b = set.add("5 Element"); // добавление(b=true) b = set.add("5 Element"); // добавление(b=false) // после добавления System.out.println(set + "add"); System.out.println(set.comparator()); //null // извлечение наибольшего и наименьшего элементов System.out.println(set.last() + " "+ set.first());}}

На экране поучим: [44Y, 56Y, 49Y, 26Y, 49Y, 2Y ]список [2Y, 26Y, 44Y, 49Y, 56Y ]множество [2Y, 26Y, 44Y, 49Y, 5 Element, 56Y ]add null 56Y 2Y

Карты отображений Карта отображений – это объект, который хранит пару ключ- значение. Поиск объекта (значения) облегчается по сравнению с множествами за счет того, что его можно найти по его уникальному ключу. Уникальность объектов-ключей должна обеспечиваться переопределением методов hashCode() и equals() пользовательским классом. Если элемент с указанным ключом отсутствует в карте, то возвращается значение null. Классы карт отображений: AbstractMap – реализует интерфейс Map ; HashMap – расширяет AbstractMap, используя хэш - таблицу, в которой ключи отсортированы относительно значений их хэш-кодов; TreeMap – расширяет AbstractMap, используя дерево, где ключи расположены в виде дерева поиска в строгом порядке. WeakHashMap позволяет механизму сборки мусора удалять из карты значения по ключу, ссылка на который вышла из области видимости приложения. LinkedHashMap запоминает порядок добавления объектов в карту и образует при этом дважды связанный список ключей.

Интерфейсы карт: Map – отображает уникальные ключи и значения; Map.Entry – описывает пару ключ- значение; SortedMap – содержит отсортированные ключи и значения; NavigableMap – добавляет новые возможности поиска по ключу. Интерфейс Map содержит следующие методы: void clear() – удаляет все пары из вызываемой карты; boolean containsKey(Object key) – возвращает true, если вызывающая карта содержит key как ключ

boolean containsValue(Object value) – возвращает true, если вызывающая карта содержит value как значение; Set > entrySet() – возвращает множество, содержащее значения карты; Set keySet() – возвращает множество ключей; V get(Object obj) – возвращает значение, связанное с ключом obj; V put(K key, V value) – помещает ключ key и значение value в вызывающую карту. При добавлении в карту элемента с существующим ключом произойдет замена текущего элемента новым. При этом метод возвратит заменяемый элемент; void putAll(Map t) – помещает коллекцию t в вызывающую карту; V remove(Object key) – удаляет пару ключ-значение по ключу key; Collection values() – возвращает коллекцию, содержащую значения карты.

Интерфейс Map.Entry содержит следующие методы: K getKey() – возвращает ключ текущей пары; V getValue() – возвращает значение текущей пары; V setValue(V obj) – устанавливает значение объекта obj в текущей паре.

Пример. import java.util.*; public class DemoHashMap { public static void main(String[] args){ HashMap hm = new HashMap (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 Set > setvalue = hm.entrySet(); System.out.println(setvalue); Iterator > i = setvalue.iterator(); while (i.hasNext()) { Map.Entry 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] 13 : 13EL 14 : 14EL 12 : 14EL 11 : 11EL

Унаследованные коллекции В языке Java применяются коллекции существовавшие в языке с момента его создания, а именно карта Hashtable, список Vector и перечисление Enumeration. Все они также были параметризованы, но сохранили свои особенности. Класс Hashtable реализует интерфейс Map, но обладает также другими методами: Enumeration elements() – возвращает перечисление (аналог итератора) для значений карты; Enumeration keys() – возвращает перечисление для ключей карты.

Пример. import java.util.*; import java.io.*; public class HashTableDemo { public static void main(String[] args) { Hashtable ht = new Hashtable (); for (int i = 0; i < 5; i++) { ht.put(i, Math.atan(i));} Enumeration ek = ht.keys(); int key; while (ek.hasMoreElements()) { key = ek.nextElement(); System.out.printf("%4d ", key);} System.out.println(""); Enumeration ev = ht.elements(); double value; while (ev.hasMoreElements()) { value = ev.nextElement(); System.out.printf("%.2f ", value);}}}

На экране получим: ,33 1,25 1,11 0,79 0,00 Класс Collections Класс Collections содержит большое количество статических методов, предназначенных для манипулирования коллекциями. В этот же класс добавлен целый ряд методов, специализированных для проверки конкретных типов коллекций, а именно: checkedList(), checkedSortedMap(), checkedMap(), checkedSortedSet(), checkedSet(), а также:

boolean addAll(Collection c, T... a) – добавляет в параметризованную коллекцию соответствующие параметризации элементы; void copy(List dest, List src) – копирует все элементы из одного списка в другой; boolean disjoint(Collection c1, Collection c2) – возвращает true, если коллекции не содержат одинаковых элементов; List emptyList(), Map emptyMap(), Set emptySet() – возвращают пустой список, карту отображения и множество соответственно; void fill(List list, T obj) – заполняет список заданным элементом ;

int frequency(Collection c, Object o) – возвращает количество вхождений в коллекцию заданного элемента; > T max(Collection coll), > T min(Collection coll) – возвращают минимальный и максимальный элемент соответственно; T max(Collection coll, Comparator comp), T min(Collection coll, Comparator comp) – возвращают минимальный и максимальный элемент соответственно, используя Comparator для сравнения;

List nCopies(int n, T o) – возвращает список из n заданных элементов; boolean replaceAll(List list, T oldVal, T newVal) – заменяет все заданные элементы новыми; void reverse(List list) – переворачивает список; void rotate(List list, int distance) – сдвигает список циклически на заданное число элементов; void shuffle(List list) – перетасовывает элементы списка; Set singleton(T o), List singletonList(T o), Map singletonMap(K key, V value) – создают множество, список и карту отображения, состоящие из одного элемента; > void sort(List list), void sort(List list, Comparator c) – сортировка списка, естественным порядком и используя Comparator соответственно; void swap(List list, int i, int j) – меняет местами элементы списка стоящие на заданных позициях.

Пример. import java.util.ArrayList; import java.util.Collections; import java.util.List; public class CollectionsDemo { public static void main(String[] args) { MyComparator comp =new MyComparator (); ArrayList list =new ArrayList (); 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 singl =Collections.singletonList(71); print(singl);}

static void print(List c) { for (int i : c) System.out.print(i + " "); System.out.println();}} import java.util.Comparator; public class MyComparator implements Comparator { public int compare(Integer n, Integer m) { return m.intValue() - n.intValue();}} На экране получим: min: 5 max 1 71

Класс Arrays В пакете java.util находится класс Arrays, который содержит методы манипулирования содержимым массива, а именно для поиска, заполнения, сравнения, преобразования в коллекцию и прочие: int binarySearch(параметры) – перегруженный метод организации бинарного поиска значения в массивах примитивных и объектных типов. Возвращает позицию первого совпадения; void fill(параметры) – перегруженный метод для заполнения массивов значениями различных типов и примитивами; void sort(параметры) – перегруженный метод сортировки массива или его части с использованием интерфейса Comparator и без него; static T[ ] copyOf(T[ ] original, int newLength) – заполняет массив определенной длины, отбрасывая элементы или дополняя null(или нулем) при необходимости;

static T[] copyOfRange(T[] original, int from, int to) – копирует заданную область массива в новый массив; List asList(T... a) – метод, копирующий элементы массива в объект типа List. Рассмотрим пример: public class ArraysEqualDemo { public static void main(String[] args) { char m1[] = new char[3]; char m2[] = { 'a', 'b', 'c' }; Arrays.fill(m1, 'a'); System.out.print("массив m1:"); for (int i = 0; i < 3; i++){ System.out.print(" " + m1[i]);}

m1[1] = 'b'; m1[2] = 'c'; if (Arrays.equals(m1, m2)){ System.out.print("\n m1 и m2 эквивалентны");} else { System.out.print("\n m1 и m2 не эквивалентны");} m1[0] = 'z'; Arrays.sort(m1); System.out.print("\n массив m1:"); for (int 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 (int 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