Java集合
数组和集合
-
- 集合与数据存储数据概述
集合、数组都是对多个数据进行存储操作的结构,简称Java容器
* 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,avi,数据库中)
-
- 数组存储的特点
> 一旦初始化以后,其长度就确定了
* > 数组一旦定义好后,其元素的类型也就确定了,我们也就只能操作指定的类型数据了
* 比如:String[] arr1; int[] arr1; Object[] arr2;
-
- 数组存储的弊端
* > 一旦初始化以后,其长度就不可修改
* > 数组中提供的方法而非常有限,对于添加,删除,插入数据等操作,非常不便,同时效率不高
* > 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
* > 数组存储数据的特点:有序,可重复。对于无序,不可重复的需求,不能满足。
-
- 集合存储的优点
Collection接口
-
- Collection接口继承树
![image-20210526170120332]()
- 单列集合框架结构
* Collection接口:单列集合,用来存储一个个的对象
* List接口:存储有序的,可重复的数据 --->"动态的数组"
* |实现类--ArrayList,LinkedList,Vector
* Set接口:存储无序的、不可重复的数据 --->"集合"
* |实现类--HashSet、LinkedHashSet、TreeSet
-
- Collection接口常用方法(JDK提供的集合API位于java.util包内)
add(Object obj),addAll(Collection coll),size(),isEmpty(),clear()contains(Object obj),containsAll(Collection coll),remve(Object obj),removeAll(Collection coll),retainAll(Collection coll),equals(Object obj)hashCode(),toArray(),iterator()
-
- Collection集合与数组的转换
//8.集合 --->数组
Object[] arrs = coll.toArray();
System.out.println(arrs);//输出数组hash值
for(int i=0;i<arrs.length;i++){//输出数组内容:只能遍历
System.out.println(arrs[i]);
}
System.out.println("********************");
//拓展:数组--->集合:调用Arrays类的静态方法
List<String> list = Arrays.asList(new String[]{"AA","bb","CC"});
System.out.println(list);//输出集合内容
System.out.println("**************************");
List<int[]> arr1 = Arrays.asList(new int[]{123456,888});
System.out.println(arr1);//[[I@61e717c2] [:一位数组 I:int
//把new int[]{}当成一个元素
System.out.println(arr1.size());//1
System.out.println("09999999999999999999");
List arr2 = Arrays.asList(new Integer[]{123456,888});
System.out.println(arr2);//[123456, 888]
System.out.println(arr2.size());//2
-
- 使用Collection集合存储对象,要求对象所属的类满足重写equals()
Iterator接口与for each循环
-
- 遍历Collection的两种方式
- 迭代器Iterator
- for each循环:
-
- java.utils包下定义的迭代器接口:Iterator
-
说明:
- Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
- GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元 素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。类似于“公 交车上的售票员”、“火车上的乘务员”、“空姐”
-
作用:遍历Collection元素,不包括map
-
如何获取实例+遍历的代码实现
Iterator it = coll.iterator(); while(it.hasNext()){ System.out.println(it.next()); } -
图示说明
![image-20210529153617249]()
-
remove()使用
@Test public void test2(){ Collection coll = new ArrayList(); coll.add(132); coll.add(new String("0ooo")); coll.add(new Person(3,"shc")); Iterator iterator=coll.iterator(); while(iterator.hasNext()){ if("0ooo".equals(iterator.next())){ iterator.remove();//删除当前指向元素 // 注意: // 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。 } } Iterator it = coll.iterator(); while(it.hasNext()){ System.out.println(it.next()); } }
-
for each就是迭代器
Collection子接口:List接口
-
- 存储的数据特点
/* Collection接口:单列集合,用来存储一个个对象
* List接口:存储有序的,可重复的数据。-->"动态"数组,替换原有的数组
* ArrayList类:作为List接口的主要实现类(线程不安全,效率高)底层:使用Object[]存储
* LinkedList类:对于频繁的插入和删除操作,使用此类效率比ArrayList高,底层使用双向链表.底层:链表
* Vector类:作为List接口的古老实现类(线程安全,效率低)(不怎么用了)/
-
- 常用方法:
* void add(int index, Object ele):在index位置插入ele元素 * boolean addAll(int index, Collection else):从index位置开始将else中的所有元素添加进来 * Object get(int index):获取指定index位置的元素 * int indexOf(Object obj):返回obj在集合中首次出现的位置 * int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置 * Object remove(int index):移除指定index位置的元素,并返回此元素 * Object set(int index, Object ele):设置指定index位置的元素为ele * List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
* 总结:常用方法 * 增:add(Object obj) * 删:remove(int idx,Object obj) * 改:set(int idx,Object obj) * 查:get(int idx) * 插入:add(int idx,Object obj) * 长度:size() * 遍历: * ① Iterator * ② for增强 * ③ 普通循环
-
- 源码
- ArrayList
* 2. ArrayList源码分析: * 2.1 jdk 7情况下 * ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData * list.add(123); //elementData[0] = new Integer(123); * ... * list.add(11) //如果此次的添加导致底层elementData数组容量不够,则扩容。 * 默认情况下,扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中。 * 结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity) * * 2.2 * jdk 8 Arraylist的变化 * ArrayList list = new Arraylist();//底层Object[] elementData初始化为{},并没有创建数组对象 * list.add(123) //第一次调用add()时,底层才创建了长度为10的数组,并将数据123天机道elementData对象中 * * ... * 后续的添加和拓展与jdk 7无异 * * * 2.3 小结: * jdk7:ArrayList对象的创建类似于单例的饿汉式 * jdk8: 懒汉式
LinkedList
* 3. LinkedList源码分析 * LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认NULL * list.add(123); 将123封装到Node中,创建了Node对象 * * LinkedList是双向链表 * 节点Node * private static class Node<E> { * E item; * Node<E> next; * Node<E> prev; * * Node(Node<E> prev, E element, Node<E> next) { * this.item = element; * this.next = next; * this.prev = prev; * } * } *
Vector
* 4. Vector源码: * jdk7和jdk8中通过vector()构造器创建对象时,底层都创建了长度为10的数组 * 在扩容方面。默认扩容为原来的数组长度的2倍
-
- 存储的元素的要求
- 添加的对象,所在的类要重写equals()
* 面试题:ArrayList、LinkedList、Vector三者的异同?* 同:三鳄类都是实现了List接口,存储数据的特点相同:存储有序的,可重复的数据
Collection的子接口:Set接口
* 1. Set接口的框架 * * Collection接口:单列集合,用于存储一个个对象 * Set接口:存储无序的,不可重复的数据 * HashSet类:作为Set接口的主要实现类:线程不安全,可以存储null值 * LinkedHashSet类:作为HashSet的子类:遍历其内部数据时,可以按照添加的顺序遍历 * TreeSet类:可以按照添加对象的指定属性,进行排序
- 存储数据的特点:无序,不可重复
- 具体的,以HashSet为例
一、Set:存储无序,不可重复的数据 1. 无序性:就是因为Hash函数 2. 不重复性: 相同的元素只能添加一个
- 元素添加过程(HashSet为例)
二、添加元素过程,以HashSet为例。hash的挂链法 hashCode()计算位置 如果数组在此位置上无元素:则a添加在这里 如果数组在此位置上有元素:则比较元素a与元素b的hash值 如果hash值不同,则元素a挂在这条链(->)上. -----》不对吧,应该也还需要遍历这条链吧,发现都不同,再加入。。。 如果hash值相同,进而调用元素a所在类的equals()方法 equals返回true,元素a添加失败 equals返回false,元素a添加成功 (->) jdk7:元素a放在数组里,原来元素b挂在链上 jdk8:元素b放在数组里,新加的元素a挂在链上
-
常用方法:Set接口中没有新声明的方法,使用的都是Collection中声明的方法
-
常用实现类
* Set接口的框架 * Collection接口:单列集合,用于存储一个个对象 * Set接口:存储无序的,不可重复的数据 * HashSet类:作为Set接口的主要实现类:线程不安全,可以存储null值 * LinkedHashSet类:作为HashSet的子类:遍历其内部数据时,可以按照添加的顺序遍历 * TreeSet类:可以按照添加对象的指定属性,进行排序
- 存储对象所在类要求
HashSet/LinkedHashSet要求:向HashSet和LinkedHashSet的实例中添加的数据,其所在的类一定要重写hashCode()和equals()重写技巧:对象中作用宇equals()方法比较的Field,都应该用来计算hashCodTreeSet 自然排序中,比较两个对象是否相同的标准为:compareTo()是否返回0;不再是equals()方法 定制排序中,比较两个对象是否相同的标准为:compare是否返回0;不再是equals()方法和元素内部的compareTo
- TreeSet使用
package com.shc.java1;import org.junit.Test;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;/** * 1. 向TreeSet中添加数据,要求是同类的对象 * * @author shc * @create 2021-05-29 14:15 */public class TreeSetTest { @Test public void test1(){ //1. 向TreeSet中添加数据,要求是同类的对象 //2. 加入的元素实现比较器,即实现Comparable接口:implements Comparable。实现方法compareTo //3. 自然排序中,比较两个对象是否相同的标准为:compareTo()是否返回0;不再是equals()方法 //4. 定制排序中,比较两个对象是否相同的标准为:compare是否返回0;不再是equals()方法和元素内部的compareTo TreeSet set = new TreeSet(); set.add(new Person(12,"Tom")); set.add(new Person(11,"shc")); set.add(new Person(88,"tes")); set.add(new Person(12,"ppp")); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } @Test public void test2(){ Comparator com = new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof Person&&o2 instanceof Person){ return Integer.compare(((Person)o1).getAge(), ((Person) o2).getAge()); }else{ throw new RuntimeException("输入对象类型错误"); } } };// TreeSet set = new TreeSet();比较时调用的是set里元素对象的compareTo TreeSet set = new TreeSet(com); set.add(new Person(12,"Tom")); set.add(new Person(11,"shc")); set.add(new Person(88,"tes")); set.add(new Person(120,"ppp")); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } }}
Map接口
- 双列集合框架:Map
-
- 常用实现类结构
/** * * Map接口:双列数据,粗出key-value对的数据。 --类似函数 * |---HashMap类:作为Map的主要实现类,线程不安全,效率高,可以存储null的key和value * |---LinkedHashMap类:保证在遍历map元素时,可以按照添加的顺序实现便利。 * 原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个,后一个元素。对于频繁的遍历执行效率高于HashMap * |---TreeMap类:保证按照添加的key-val进行排序,实现排序遍历,此时考虑key的自然排序或定制排序 * |---Hashtable类:作为Map的古老实现类,线程安全,效率低,不能存储null的kay和value * |---Properties类:常用来处理配置文件,key和value都是String类型 * 面试题 * 1. HashMap的底层实现原理? * 2、HashMao和Hashtable的底层原理 * 3. CurretnHashMap和Hashtable的异同?
-
- 存储结构的理解
* 二、Map结构的理解: * Map中的key:无序的,不可重复的,使用set存储所有的key -->要重写equals()和hashCode(),以HashMap为例。 * Map中的value:无序的,可重复的。使用Collection存储所有的value。 -->value所在的类要重写equals() * 一个键值对:key-value构成了一个Entry对象。 * Map中的entry:无序的,不可重复的,使用Set存储所有的entry
- 图示

-
- 常用方法
*总结:常用方法: * 添加:put(Object key,Object value) * 删除:remove(Object key) * 修改:get(Object key) * 长度:size() * 遍历:keySet()/values()/entrySet()
-
- 内存结构的说明
- HashMap在jdk7中实现原理
* 三、HashMap的底层实现原理 * 以jdk7为例说明 * HashMap map = new HashMap(); * 在实例化以后,底层创建了长度是16的一位数组Entry[] table * map.put(key1,value1); * 首先,调用key1所在的类hashCode()计算key1的hash值,此hash值经过某种算法计算以后,得到Entry数组中的存放位置 * 如果此位置上的数据为空,此时的key1-value添加成功 ---情况1 * 如果此位置上的数据不畏空,(意味着此位置上存在一个或多个数据(以链表形式存在))比较key1和已经存在的一个或多个数据的hash值 * 如果key1的hash值和已经存在的数据的hahs值都不相同,则添加key1-value1. ---情况1 * 如果key1的hash值和已经存在的某一个数据(key2-value)的hash值相同,继续比较:调用key1所在的类的equals(key2) * 如果equals()返回false,此时key1-value添加成功。 --情况3 * 如果equals()返回true,使用value替换value2 * 在不断添加的过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容,默认的扩容为原来的二倍 * DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16 * MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30 * DEFAULT_LOAD_FACTOR:HashMap的默认加载因子 * TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树 * UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
- jdk8与jdk7的不同之处
* jdk8与jdk7的不同。 * 1. new HashMap():底层没有实现长度为16的数组 * 2. jdk 8底层的数组是:Node[],而非Entry[] * 3. 首次调用put()方法时,底层创建长度为16的数组 * 4. jdk底层结构只有数组+链表。jdk8中底层结构:数组+链表+红黑树 * 当数组的某一个索引位置上的元素以链表形式存在的数据>8,且当前数组元素>64时,此时此索引位置上的所有数据改为使用红黑树存储
- HashMap底层典型属性
* DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16 * MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30 * DEFAULT_LOAD_FACTOR:HashMap的默认加载因子 * TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树 * UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
- LinkedHashMapi底层原理(了解)
LInkedHashMap底层结构与HashMap相同,因为LinkedHashMap继承于HashMap,区别在于:LinkedHashMap内部使用了Entry。替换HashMap中的Node

- TreeMap使用
//向TreeMap中添加key-value,要求key必须是同一个类创建的对象 //因为要按照key进行排序:自然排序,定制排序 //自然排序 被比较元素implements Comparable
- Collection工具类
- 作用:操作Collection和Map的工具类。
- 对比:Iterator:只操作Collection及其实现的籍人口
每日一考
-
集合Collection中存储的如果是自定义类的对象,需要自定义重写哪个方法?why?
- equals()方法
- list也要重写equals()方法(在contains,remove啥的时候调用)
- set:
- (HashSet,LinkedHashSet):equals(),hashCode()。
- (TreeSet为例)
- Comparable:compareTo(Object obj)
- Comparator:compareTo(Object o1,Object o2)
-
ArrayList,Linked,Vector三者的相同点于不同点?【面试题】
-
List接口的常用方法
- 增:add(Object obj)
- 删:reomve(Object obj)
- 改:set(int idx,Object obj)
- 查:get(int idx)
- 插:add(int idx,Object obj)
- 大小:size()
- 遍历:Iterator;for each;for
-
如何使用Iterator和增强for循环遍历List。举例说明
-
Set存储数据特点?常见实现类?特点?
- HashSet,LinkedList,TreeSet
每日一考
-
- Map存储数据的特点是什么?并指明key,value,entry存储数据的特点
- 双列数据,存储key-value对数据
- key:无序的,不可重复的。-->Set存储
- value:无序的,可重复的。-->Collection存储
- key-value:无序的,不可重复。-->Set存储
-
- HashMap的底层实现原理(jdk8)(必须会)
-
- Map中常用实现类有哪些?各自特点?
- HashMap
- LinkedHashMap
- TreeMap
- Hashtable
- Properties
-
- 如何遍历Map中的key-value对
-
- Collections和Collection的区别?



浙公网安备 33010602011771号