秦皇岛网站搜索排名,wordpress斜杠,网站首页模板怎么做策划,公开招标网站单列集合 为了存储不同类型的多个对象#xff0c;Java提供了一些特殊系列的类#xff0c;这些类可以存储任意类型的对象#xff0c;并且存储的长度可变#xff0c;这些类统称为集合。可以简单的理解为一个长度可变#xff0c;可以存储不同数据类型的动态数组。集合都位于j…单列集合 为了存储不同类型的多个对象Java提供了一些特殊系列的类这些类可以存储任意类型的对象并且存储的长度可变这些类统称为集合。可以简单的理解为一个长度可变可以存储不同数据类型的动态数组。集合都位于java.util包中使用集合时必须导入java.util包。在学习具体集合之前先了解一下整个集合的核心继承体系 单列集合 双列集合 以上两张图中红线框里的是接口类型蓝线框里的是具体的实现类。集合里的核心接口如下表
集合中的核心接口 接口 描述Collection 集合中最基本的接口一般不直接使用该接口 ListCollection的子接口一般用于存储有序可重复有索引的对象是集合中最常用的接口之一SetCollection的子接口一般用于存储无序不可重复无索引的对象Map双列集合的根接口用于存储一组键值对象提供键到值的映射
一Collection接口 Collection接口是单列集合的顶层接口ListSet使它的子接口既然是接口就不能直接使用需要通过实现类 它最常见的实现类是ArrayListLinkedListHashSet和TreeSet它定义了各种具体实现类的共性其他单列集合(实现类直接或间接的继承该接口。
Collection接口的常用方法 方法声明 功能描述boolean add(Object o)相当前集合中添加一个元素boolean addAll(Collection c)将指定集合c中的所有元素添加到当前集合中void clear()清空当前集合中的所有元素boolean remove(Object o)删除当前集合中的指定元素boolean removeAll(Object c)删除当前集合中包含的集合c的所有元素boolean isEmpty()判断当前集合是否为空boolean contains(Object o)判断当前集合是否包含某个元素boolean containsAll(Collection c)判断当前集合是否包含指定集合c的所有元素Iterator iterator()返回当前集合的迭代器。迭代器用于遍历集合中的所有元素int size()获取当前集合的元素个数集合长度
1Collection集合的遍历 Collection这个系列集合的通用的3种遍历方式
方法一Iterator迭代器 方法new出来的集合调用iterator方法创建一个迭代器对象用来遍历集合。不同之处是遍历过程可删除元素 public static void main(String[] args) {//迭代器循环//1创建一个ArrayList集合CollectionString listnew ArrayList();//向集合中添加元素list.add(肘子);list.add(大王);list.add(晚上好呀);//2new出来的集合调用iterator方法创建一个迭代器对象用来遍历集合//迭代器就好比是一个箭头默认指向集合的0索引处IteratorString iterator list.iterator();//遍历while (iterator.hasNext()){ //hasNext():判断当前集合中的指针位置是否存有元素对象有返回true没有返回falseString s iterator.next();//next():获取元素并后移指针//删除元素/*迭代器遍历时不能用集合中的方法对元素进行增加或删除如果实在要删除可以用迭代器提供的remove方法进行删除如果需要添加暂时没有方法*/if(s.equals(大王)){iterator.remove();}System.out.println(s);}System.out.println(list);
//迭代器使用完毕指针不会复位}
结果 注意
1迭代器在遍历集合的时候是不依赖索引的他是通过创建指针并移动指针的方式来获取集合中的元素
2迭代器需要掌握的3个方法
通过集合的iterator()方法获取一个迭代器对象迭代器就好比是一个箭头默认指向集合的0 索引处通过迭代器对象的hasNext()方法判断当前集合中的指针位置是否存有元素对象有返回true没有返回false通过迭代器对象的next()方法获取元素并后移指针每一个next()方法都代表一次获取元素后移指针所以一次循环里写一个next()方法。
3迭代器的四个细节
如果当前位置没有元素还要强行获取会报NoSuchElementException迭代器遍历完毕指针不会复位所以再次遍历需要重新创建一个迭代器对象遍历的循环中只能用一次next()方法,因为运行一次指针就后移一位并获取当前指向的对象迭代器遍历时不能用集合里的方法进行增加或者删除只能用迭代器里的方法。
方法二增强for public static void main(String[] args) {//增强for循环//创建一个集合CollectionString listnew ArrayList();//向集合中添加元素list.add(肘子);list.add(大王);list.add(晚上好呀);//遍历for (String s : list) {//sbbb;//s属于第三方变量s改变了但是集合里面的元素不会改变System.out.println(s);System.out.println(list);}}
结果 方法三Lambda表达式
public static void main(String[] args) {//创建集合CollectionString listnew ArrayList();//向集合中添加元素list.add(肘子);list.add(大王);list.add(晚上好呀);//遍历//底层原理//其实也会自己遍历依次得到每一个元素//得到的元素传递给下面的accept()方法//s表示集合中的每一个元素list.forEach(new ConsumerString() {Overridepublic void accept(String s) {System.out.println(s);}});System.out.println(------------------);//lambda表达式:()-{}//():与方法的形参想匹配数据类型可省略形参只有一个小括号可省略//{}与方法体相匹配list.forEach(s- System.out.println(s));//上面forEach的简化版}
结果 2List接口 List接口继承Collection接口允许存储重复的元素所有的元素以线性方式存储。在程序中可以通过索引所有访问List接口实例中存储的元素且存储的元素是有序的。 List集合作为Collection集合的子接口不但继承了Collection接口中的全部方法而且还增加了根据元素索引操作集合的特有方法。
特点有序可重复有索引
在java.util包可以找到List接口 它是一个ListIterator接口工厂。通过ListIterator我们可以向前和向后迭代列表。List接口的实现类是ArrayList、LinkedList、Stack和Vector。ArrayList和LinkedList在Java编程中被广泛使用Vector类自Java 5以来已弃用。 2.1接口的声明
public interface ListE extends CollectionE ; 让我们详细说明如何在List类中创建对象或实例
因为List是一个接口所以不能按List类型创建对象。我们总是需要一个实现这个List的类来创建对象如ArrayList在Java 1.5中引入泛型之后可以限制可以存储在List中的对象的类型 就像其他几个由用户定义的“类”实现的用户定义的“接口”一样List是一个“接口”由ArrayList等类实现实现在java.util 包下
2.2语法
ListE list new ArrayListE (); E: 泛型数据类型用于设置 objectName 的数据类型只能为引用数据类型。添加的元素为基本类型的话就要使用它的包装类如下表list: 创建的集合名
2.3操作
现在让我们使用List 接口执行各种操作以便更好地理解这些操作。我们将讨论下面列出的操作以及稍后通过干净的java代码实现的操作。
由于List是一个接口它只能与实现该接口的类一起使用。现在让我们看看如何对List执行一些常用操作。
使用add()方法向List类添加元素使用set()方法更新List类中的元素使用get()方法返回元素使用remove()方法删除元素
现在让我们分别讨论操作并在代码中实现相同的操作以便更好地掌握它。
1.添加操作
为了向列表中添加元素可以使用add()方法。此方法被重载以基于不同参数执行多个操作。
参数:接受2个参数分别为:
add(Object):该方法用于在List的末尾添加一个元素。add(int index, Object):该方法用于在List的特定索引处添加元素
2. 更新操作
添加元素之后如果我们希望更改元素可以使用set(int index,E element)方法来完成。因为List有索引的所以我们想要更改的元素会被该元素的索引所引用。因此此方法接受一个索引和需要插入到该索引处的更新元素。
3. 返回操作
添加元素之后如果我们需要得到某个元素可以使用get(int index)方法来完成。
4. 删除操作
为了从列表中删除一个元素我们可以使用remove()方法。此方法被重载以基于不同参数执行多个操作
Parameters:
remove(Object):该方法用于简单地从List中删除一个对象。如果有多个这样的对象则删除第一个出现的对象。remove(int index):由于List被建立了索引所以这个方法接受一个整数值它只是简单地删除List中特定索引处的元素。删除元素后所有元素都向左移动以填充空间并更新对象的索引。
实例
public static void main(String[] args) {//创建集合EListString listnew ArrayList();//添加元素 void add(int index,E element)list.add(肘子);list.add(大王);list.add(晚上好呀);list.add(上头的85批);System.out.println(原本集合list);//删除指定元素 E remove(int index)delete(list);//修改指定索引元素 E set(int index,E element)alter(list);//返回指定索引元素 E get(int index)obtainE(list);}private static void delete(ListString list) {System.out.println(删除指定元素---------------);//表示删除索引为0的元素list.remove(1);System.out.println(表示删除索引为0的元素: list);//删除第一个元素手动装箱手动把基本数据类型肘子转换成String类型变成一个对象String iString.valueOf(大王);list.remove(i);//为什么相同的remove()方法运行的效果不同// 在调用方法的时候如果方法出现了重载// 优先调用型参与实参数据类型相同的那一个System.out.println(删除‘大王’元素list);}private static void alter(ListString list) {System.out.println(替换指定元素--------------------只能替换存在的元素);String s1 list.set(0, 替换索引0);System.out.println(返回的是被替换的元素:s1); //返回的是被替换的元素System.out.println(list集合list);}private static void obtainE(ListString list) {System.out.println(返回指定索引[0]元素-----------);String s list.get(0);System.out.println(s);System.out.println(集合listlist);}
结果 2.4 ArrayList
1概念 ArrayList 类是一个实现了List接口的单列集合实现类可以动态修改的数组与普通数组的区别就是它是没有固定大小的限制我们可以添加或删除元素。ArrayList 继承了 AbstractList 并实现了 List 接口。
2ArrayList用于
频繁访问列表中的某一个元素。只需要在列表末尾进行添加和删除元素操作不适合做大量的增删操作而适合元素的查找 2.5 LinkedList
1概念 java.util.LinkedList是一个实现了List接口的单列集合实现类底层是一个双向链表链表中的每一个元素都使用引用的方式记录它的前一个元素和后一个元素从而将所有的元素连接起来。同时实现了实现了List和Deque接口
优点
由于LinkedList底层实现是双向链表所以在进行插入和删除操作方面具有高效性。由于LinkedList是动态的数据结构因此在使用时不需要预先分配空间由于LinkedList实现了Deque接口 在集合的队首和队尾可以进行高效的插入和删除操作
缺点
由于LinkedList底层实现是双链表所以从集合中访问某个元素时需要从头开始遍历整个链表所以其查询操作慢由于LinkedList在进行元素对象存储时需要将指向下一个元素和上一个元素的指针同时进行存储其占用的内存空间相比ArrayList数组要更多。由于LinkedList是基于链表实现的因此不支持随机访问只能通过遍历整个链表来访问元素 所以 LinkedList 的增加和删除的操作效率更高而查找和修改的操作效率较低。 2 LinkedList常用于
你需要通过循环迭代来访问列表中的某些元素。需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
3Set接口 List接口和Set接口都是Collection的子接口两者不同的是Set系列集合添加的元素是无序、不重复、无索引的。
Set系列集合
无序存取顺序不一致不重复可以去除重复的元素无索引没有带索引的方法所以不能使用普通for循环遍历也不能通过索引来获取元素
Set集合的实现类
HashSet:无序不重复五索引LinkedHashSet:有序不重复无索引TreeSet:可排序不重复无索引
Set接口中的方法基本与Collection的API一致。没有额外方法去学习直接使用Collection中常见方法就行。
利用Set系列集合存储字符串并遍历
package day0606SetDemo;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;public class SetDemo1 {public static void main(String[] args) {//1,创建一个Set集合的对象SetString snew HashSet();boolean b s.add(肘子);boolean b2 s.add(西施);boolean b3 s.add(花木兰r);//2,添加元素//add()方法的返回值是Boolean类型对于List来说没有意义因为它允许元素重复不管添加什么都返回true而Set不允许元素重复boolean b1 s.add(肘子);System.out.println(b);//trueSystem.out.println(b1);//false//3打印集合//无序System.out.println(s);//[肘子, 花木兰r, 西施]//31迭代器遍历IteratorString iterator s.iterator();while (iterator.hasNext()){//判断当前指向的位置是否有元素String next iterator.next();//获取当前元素并指针后移一位System.out.println(next);}System.out.println(-------------------------);//32增强forfor (String s1 : s) {System.out.println(s1);}System.out.println(-------------------------);//33Lambda表达式s.forEach( str-System.out.println(str));//str表示集合里的每一个元素}
}
注意 结果 1HashSet
HashSet底层原理
HashSet底层采取哈希表核心存储数据哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
JDK8之前数组链表JDK8开始数组链表红黑树
哈希值 哈希表在底层它是有数组存在的添加数据它不是由0索引开始挨个往后添加的而是根据数组长度和哈希值公式计算出元素应该存入数组中哪个位置
对象的整数表现形式根据hashCode方法算出来的int类型的整数该方法定义在Object类中所有对象都可以调用默认使用地址值进行计算意义不是很大一般情况下会重写hashCode方法利用对象内部的属性值计算哈希值
对象的哈希值特点 如果没有重写hashCode方法不同对象计算出的哈希值是不同的 如果已经重写hashCode方法不同对象只有属性值相同计算出的哈希值就是一样的小部分情况下不同的属性值或者不同的地址值计算出的哈希值也有可能一样哈希碰撞
重写hashCode方法 右键--generate--equals and hashCode--next--next--next--finish Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;Demo2Stu demo2Stu (Demo2Stu) o;return age demo2Stu.age Objects.equals(name, demo2Stu.name);}Overridepublic int hashCode() {return Objects.hash(name, age);}
总结
HashSet集合的底层数据结构是什么样的
JDK8之前数组链表JDK8开始数组链表红黑树 底层添加数据原理是什么
创建一个默认长度为16默认加载因子为0.75的数组数组名为table加载因子作用扩容。当数组存储长度达到16*0.7512时数组扩增1倍数组长度变为32如果集合中存储的是自定义对象则必须要重写hashCode和equals方法根据公式计算出元素在数组当中应该存入的位置判断该位置是否为null如果是null直接存入如果该位置不为null表是有元素则调用equals方法比较属性值一样不存不一样存入数组。JDK8之前新元素放到数组当中原本的元素连接到新元素的下面形成链表。JDK8开始新元素连接到原本元素的后面形成链表当链表的长度大于8而且数组长度大于等于64时链表转成红黑树JDK8以后 HashSet为什么存和取的顺序不一样 因为它是从0索引开始一条链表一条链表开始遍历的。数组有索引集合没有 HashSet为什么没有索引
因为它是由数组、链表、红黑树3个组合而成的无法定义索引
HashSet利用什么机制保证数据去重的 HashCode方法和equals方法
HashCode方法根据哈希值确定数据添加到哪个位置equals方法判断要添加的数据与原本该位置上的数据是否重复
2LinkedHashSet LinkedHashSet集合的特点和原理是什么
有序、不重复、无索引底层基于哈希表但多了一个双向链表记录添加顺序
这个双向链表的目的是存取有序而不是为了提高增删效率
以后如果要数据去重我们使用哪个
默认使用HashSet如果要求去重且存取有序才使用LinkedHashSet