предисловие
Использование интерфейса Collection было представлено в предыдущем сообщении в блоге. В этой статье будет представлено использование подклассов в интерфейсе Collection. Что касается того, почему вы хотите поговорить о его подклассах, не спрашивайте меня. Какой? Какой-то Сяобай читает статью, которую я написал... Извините, извините за то, что я только что сказал, пожалуйста, позвольте блогеру реорганизовать язык... кхм, что касаетсяЗачем говорить о подклассах интерфейса Collection?? Маленькие белые детские туфли, интерфейс Коллекция интерфейс, какова цель интерфейса? Это определение набора спецификаций. Без конкретного класса для реализации интерфейса интерфейс бессмысленен! Маленькие белые детские туфли, что ты делаешь?
Другое дело, что если вы не знакомы с интерфейсом Коллекции, белая детская обувьнастоятельно рекомендуетсяСначала прочитайте эту статью после того, как разберетесь с интерфейсом Коллекции, в противном случае толькоМенее эффективны! Ну, я знаю, что это блоггер. Я настоятельно рекомендую, чтобы детская обувь Xiaobai не искала. Ничего страшного, у блогера нет другой цели, просто чтобы детская обувь Xiaobai хорошо выучила java, поэтому я подготовила после этой статьи~Нажмите на синий шрифт, чтобы войти~Коллекция collection и принцип реализации итератора Iterator
@[toc]
Интерфейс списка
Далее, давайте вместе изучим два общих подкласса в Collection.java.util.List
собирать,java.util.Set
собирать.
1.1 Введение в интерфейс списка
java.util.List
Интерфейс наследуется отCollection
интерфейс, в коллекции ListЭлементы могут повторяться,Элементы упорядочены. Все элементы хранятся линейным образом, в программе к указанному элементу в коллекции можно получить доступ через индекс, а порядок хранения элементов согласуется с порядком поиска.
Анализ возможностей интерфейса списка:
- Упорядоченный доступ к элементам: Например, порядок запоминания элементов "И", "Да", "Пэ", "Нечет", то в наборе элементы записываются в порядке "Я", "Да", "Пэ" , "Нечетное" Завершено.
- коллекция с индексом: То же самое и с индексом массива
- повторение элемента: по элементам
equals
Способ сравнения элементов для дубликатов.
1.2 Общие методы в интерфейсе List
Как подчиненный интерфейс коллекции Collection, List не только наследует все методы интерфейса Collection, но и некоторыеиндекс элементаПриходитьКоллекция действийизуникальныйМетоды, как показано ниже:
public void add(int index, E element)
: добавить указанный элемент в указанную позицию в наборе. -public E get(int index)
: возвращает элемент в указанной позиции в коллекции.public E remove(int index)
: удаляет элемент в указанной позиции в списке, возвращая удаленный элемент.public E set(int index, E element)
: заменить элемент в указанной позиции в коллекции указанным элементом и вернуть значение элемента перед обновлением.
Методы, специфичные для коллекции списков, связаны с индексом, код показан ниже:
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List<String> list = new ArrayList<String>();
// 往 尾部添加 指定元素
list.add("安琪拉屎");
list.add("刘备胎");
list.add("廉颇妇");
System.out.println(list);
// add(int index,String s) 往指定位置添加
list.add(1,"猪脚亮");
System.out.println(list);
// String remove(int index) 删除指定位置元素 返回被删除元素
// 删除索引位置为2的元素
System.out.println("删除索引位置为2的元素");
System.out.println(list.remove(2));
System.out.println(list);
// String set(int index,String s)
// 在指定位置 进行 元素替代(改)
// 修改指定位置元素
list.set(0, "东皇太二");
System.out.println(list);
// String get(int index) 获取指定位置元素
// 跟size() 方法一起用 来 遍历的
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
//还可以使用增强for
for (String string : list) {
System.out.println(string);
}
}
}
Подкласс списка
2.1 Коллекция ArrayList
java.util.ArrayList
Структура хранилища данных коллекциимножествоструктура. элементМедленные добавления и удаления, быстрый поиск, потому что наиболее часто используемые функции в повседневной разработке — это запрос данных и обход данных, поэтомуArrayList
является наиболее часто используемым набором.
2.2 Коллекция LinkedList
java.util.LinkedList
Структура хранилища данных коллекциисвязанный списокструктура. элементДобавляйте и удаляйте быстро, ищите медленноколлекция.
LinkedList — это двусвязный список, так как же выглядит двусвязный список?
В реальной разработке добавление и удаление элемента коллекции часто включает операции начала и конца, а LinkedList предоставляет большое количество методов операций начала и конца. В качествеПросто пойми:
-
public void addFirst(E e)
: вставляет указанный элемент в начало этого списка. -
public void addLast(E e)
: добавить указанный элемент в конец этого списка. -
public E getFirst()
: возвращает первый элемент этого списка. -
public E getLast()
: возвращает последний элемент этого списка. -
public E removeFirst()
: удаляет и возвращает первый элемент этого списка. -
public E removeLast()
: удаляет и возвращает последний элемент этого списка. -
public E pop()
: извлекает элемент из стека, представленного этим списком. -
public void push(E e)
: Поместите элемент в стек, представленный этим списком. -
public boolean isEmpty()
: возвращает true, если список не содержит элементов.
LinkedList является подклассом List.Можно использовать методы LinkedList в List.Мы не будем подробно представлять их здесь.Нам нужно только понять уникальные методы LinkedList. Во время разработки коллекцию LinkedList также можно использовать в качестве стека, структуры очереди. (ты можешь понять)
Код метода следующий:
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
//添加元素
link.addFirst("大乔");
link.addFirst("小桥");
link.addFirst("老乔");
System.out.println(link);
// 获取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
// 删除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while (!link.isEmpty()) { //判断集合是否为空
System.out.println(link.pop()); //弹出集合中的栈顶元素
}
System.out.println(link);
}
}
Ну вот, сбор списков подходит к концу.
Установить интерфейс
3.1 Знакомство с интерфейсом Set
java.util.Set
интерфейс иjava.util.List
Тот же интерфейс, также унаследованный отCollection
интерфейс, связанный сCollection
Методы в интерфейсе в основном одинаковые, и нет правильногоCollection
Интерфейс функционально расширен, просто чемCollection
Интерфейс более строгий. а такжеList
Интерфейс другой,Set
в интерфейсеЭлементы не в порядкеа такжеНе повторяется, просто всев отличие от списка, set гарантирует, что сохраненные элементы не будут повторяться в соответствии с определенными правилами.
Set
Коллекции имеют несколько подклассов, здесь мы представляем некоторые из них.java.util.HashSet
,java.util.LinkedHashSet
эти два набора.
Способ извлечения элементов из коллекции Set может быть: итератор, расширенный для.
Установить подкласс интерфейса
4.1 Введение в коллекцию HashSet
java.util.HashSet
даSet
один из интерфейсовКласс реализации, хранящиеся в нем элементынеповторяемый, неупорядоченный(то есть порядок доступа несовместим).java.util.HashSet
Базовая реализация на самом деле являетсяjava.util.HashMap
служба поддержки.
HashSet
Он основан на хеш-значении объекта для определения места хранения элемента в коллекции, поэтому он имеет хорошую производительность доступа и поиска. Способ гарантировать уникальность элемента зависит от:hashCode
а такжеequals
метод.
Давайте сначала воспользуемся хранилищем коллекции Set, посмотрим на явление, а потом объясним принцип:
public class HashSetDemo {
public static void main(String[] args) {
//创建 Set集合
HashSet<String> set = new HashSet<String>();
//添加元素
set.add(new String("安琪拉屎"));
set.add("刘备胎");
set.add("猪八戒烟");
set.add("安琪拉屎");
//遍历
for (String name : set) {
System.out.println(name);
}
}
}
Вывод выглядит следующим образом, указывая на то, что повторяющиеся элементы не могут храниться в коллекции:
安琪拉屎
刘备胎
猪八戒烟
По результатам мы обнаружили, что сохраняется только одна строка «Ангельское дерьмо», то есть не сохраняется заданный набор повторяющихся элементов.
4.2 Структура хранилища данных коллекции HashSet (хэш-таблица)
Что такое хеш-таблица?
существуетJDK1.8До,Нижний слой хеш-таблицы реализован с помощью массива + связанный список., даже если для разрешения конфликтов используется связанный список, связанные списки с одним и тем же значением хеш-функции сохраняются в связанном списке. Однако когда в корзине много элементов, то есть когда много элементов с одинаковыми хеш-значениями, эффективность последовательного поиска по значению ключа низка. а такжеВ JDK1.8,Хранение хеш-таблицы реализовано массивом + связным списком + красно-черным деревом, когда длина связанного списка превышает порог (8), связанный список преобразуется в красно-черное дерево, что значительно сокращает время поиска.
Проще говоря, хеш-таблица реализована в виде массива + связанного списка + красно-черного дерева (JDK1.8 добавляет красно-черную часть дерева), как показано на следующем рисунке.
Увидев эту картинку, возникает детская обувь, чтобы спросить, а как такая хранится? Смотрите картинку ниже, чтобы понять в общем,JDK1.8Введение красно-черного дерева значительно оптимизирует производительность HashMap, поэтому для обеспечения уникальности элементов коллекции HashSet она фактически определяется по методам hashCode и equals объекта. Если мы сохраняем пользовательский объект в коллекции, для обеспечения его уникальности мы должны переопределить методы hashCode и equals, чтобы установить метод сравнения, принадлежащий текущему объекту.Что касается структур данных, то про массивы и связанные списки я уже писал ранее, для вашего удобства вставлю их ниже.
[Структура данных 01] Говоря о массивах
[Структура данных 03] Говоря о связанном списке
Какой? Хотите увидеть красно-черное дерево? Эх... Я еще не написала. Если не тороплюсь к блогеру, то немного отложу. ~В конце концов, я занята~ Мне очень не терпится посмотрите, как блогер пытается найти время, чтобы написать статью...
4.3 Анализ исходного кода
QnQ
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
// 底层使用HashMap来保存HashSet中所有元素。
private transient HashMap<E,Object> map;
// 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。
private static final Object PRESENT = new Object();
/**
* 默认的无参构造器,构造一个空的HashSet。
*
* 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。
*/
public HashSet() {
map = new HashMap<E,Object>();
}
/**
* 构造一个包含指定collection中的元素的新set。
*
* 实际底层使用默认的加载因子0.75和足以包含指定
* collection中所有元素的初始容量来创建一个HashMap。
* @param c 其中的元素将存放在此set中的collection。
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* 以指定的initialCapacity和loadFactor构造一个空的HashSet。
*
* 实际底层以相应的参数构造一个空的HashMap。
* @param initialCapacity 初始容量。
* @param loadFactor 加载因子。
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<E,Object>(initialCapacity, loadFactor);
}
/**
* 以指定的initialCapacity构造一个空的HashSet。
*
* 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。
* @param initialCapacity 初始容量。
*/
public HashSet(int initialCapacity) {
map = new HashMap<E,Object>(initialCapacity);
}
/**
* 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。
* 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。
*
* 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。
* @param initialCapacity 初始容量。
* @param loadFactor 加载因子。
* @param dummy 标记。
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}
/**
* 返回对此set中元素进行迭代的迭代器。返回元素的顺序并不是特定的。
*
* 底层实际调用底层HashMap的keySet来返回所有的key。
* 可见HashSet中的元素,只是存放在了底层HashMap的key上,
* value使用一个static final的Object对象标识。
* @return 对此set中元素进行迭代的Iterator。
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
/**
* 返回此set中的元素的数量(set的容量)。
*
* 底层实际调用HashMap的size()方法返回Entry的数量,就得到该Set中元素的个数。
* @return 此set中的元素的数量(set的容量)。
*/
public int size() {
return map.size();
}
/**
* 如果此set不包含任何元素,则返回true。
*
* 底层实际调用HashMap的isEmpty()判断该HashSet是否为空。
* @return 如果此set不包含任何元素,则返回true。
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* 如果此set包含指定元素,则返回true。
* 更确切地讲,当且仅当此set包含一个满足(o==null ? e==null : o.equals(e))
* 的e元素时,返回true。
*
* 底层实际调用HashMap的containsKey判断是否包含指定key。
* @param o 在此set中的存在已得到测试的元素。
* @return 如果此set包含指定元素,则返回true。
*/
public boolean contains(Object o) {
return map.containsKey(o);
}
/**
* 如果此set中尚未包含指定元素,则添加指定元素。
* 更确切地讲,如果此 set 没有包含满足(e==null ? e2==null : e.equals(e2))
* 的元素e2,则向此set 添加指定的元素e。
* 如果此set已包含该元素,则该调用不更改set并返回false。
*
* 底层实际将将该元素作为key放入HashMap。
* 由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key
* 与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true),
* 新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变,
* 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中,
* 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。
* @param e 将添加到此set中的元素。
* @return 如果此set尚未包含指定元素,则返回true。
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
/**
* 如果指定元素存在于此set中,则将其移除。
* 更确切地讲,如果此set包含一个满足(o==null ? e==null : o.equals(e))的元素e,
* 则将其移除。如果此set已包含该元素,则返回true
* (或者:如果此set因调用而发生更改,则返回true)。(一旦调用返回,则此set不再包含该元素)。
*
* 底层实际调用HashMap的remove方法删除指定Entry。
* @param o 如果存在于此set中则需要将其移除的对象。
* @return 如果set包含指定元素,则返回true。
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
/**
* 从此set中移除所有元素。此调用返回后,该set将为空。
*
* 底层实际调用HashMap的clear方法清空Entry中所有元素。
*/
public void clear() {
map.clear();
}
/**
* 返回此HashSet实例的浅表副本:并没有复制这些元素本身。
*
* 底层实际调用HashMap的clone()方法,获取HashMap的浅表副本,并设置到HashSet中。
*/
public Object clone() {
try {
HashSet<E> newSet = (HashSet<E>) super.clone();
newSet.map = (HashMap<E, Object>) map.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
}
Грубо говоря, HashSet — это HashMap с ограниченными функциями, поэтому, если вы понимаете принцип реализации HashMap, этот HashSet, естественно, будет работать.Для объектов, сохраненных в HashSet, в основном необходимо правильно переписать метод equals и метод hashCode на убедитесь, что единственным объектом, помещенным в объект Set, является секс,Хотя Set не помещает в него повторяющиеся элементы, лучше сказать, что базовая карта напрямую заменяет исходное значение.(Возвращаемое значение метода put этого набора действительно интересно). HashSet не предоставляет метод get().Как и HashMap, Set неупорядочен и может быть получен только путем итерации.
4.4 HashSet хранит элементы пользовательского типа
При сохранении элементов пользовательского типа в HashSet вам необходимо переписатьhashCode
а такжеequals
метод, чтобы установить свой собственный способ сравнения, чтобы обеспечитьHashSet
Предметы в коллекции уникальны
Создайте пользовательский класс Student
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class HashSetDemo2 {
public static void main(String[] args) {
//创建集合对象 该集合中存储 Student类型对象
HashSet<Student> stuSet = new HashSet<Student>();
//存储
Student stu = new Student("程序员老王", 43);
stuSet.add(stu);
stuSet.add(new Student("程序员小王", 44));
stuSet.add(new Student("程序员老王", 43));
stuSet.add(new Student("程序员秃头哥", 23));
stuSet.add(stu);
for (Student stud : stuSet) {
System.out.println(stud);
}
}
}
执行结果:
Student [name=程序员小王, age=44]
Student [name=程序员老王, age=43]
Student [name=程序员秃头哥, age=23]
4.5 LinkedHashSet
Мы знаем, что HashSet гарантирует уникальность элементов, но элементы хранятся в произвольном порядке, поэтому мы хотим обеспечить порядок, что нам делать? Ниже HashSet есть подклассjava.util.LinkedHashSet
, которая представляет собой структуру хранения данных, объединяющую связанный список и хеш-таблицу.
код показывает, как показано ниже:
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("秃头哥");
set.add("地中海哥");
set.add("平头哥");
set.add("假发哥");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
秃头哥
地中海哥
平头哥
假发哥
Наконец, приглашаю всех обратить внимание на мою официальную учетную запись, обсудить технологии вместе, тосковать по технологиям, заниматься технологиями...