Java学习历程---集合

1 单例集合框架图示

---->Collection接口:单例集合,用来存储一个一个的对象

>List接口:存储有序的、可重复的数据 ---->”动态“数组

>ArratList / LinkedList / Vector

>Set接口:存储无序的、不可重复的数据 ---->数学意义上的”集合“

>HashSet / LinkedHashSet / TreeSet

 

---->常用方法


Collection coll= new ArrayList();
//1.add(Object obj)
coll.add("AA");
coll.add(123);
coll.add("");
//2.size()
System.out.println(coll.size());
//3.addAll(Collection col);将另一个Collection实现类的元素添加进来
Collection col = new ArrayList();
col.add(0);
col.add("0");
coll.addAll(col);
System.out.println(coll.size());
//4.isEmpty();
System.out.println(coll.isEmpty());
//5.clear();清空元素
coll.clear();
System.out.println(coll.isEmpty());
//6.contains(Object obj);判断当前集合是否包含obj
//掉用的是存储对象的equals()
System.out.println(coll.contains(123));
System.out.println(coll.contains(new String("bb")));//这里判断的是内容,用的是equals()
System.out.println(coll.contains(new Person("name",18)));//这里的equals的没有重写
//7.containsAll(Collection col);
//判断形参col中的所有元素是否都在当前集合中
Collectioncol=newArrayList();
col.add(123);
System.out.println(coll.containsAll(col));
//8.remove(Objectobj)
//如果有重复的,只移除一个
//调用的也是equals
coll.remove(123);
System.out.println(coll);
//9.removeAll(Collection col);
//移除和col中一样的元素,就是做一个差集
coll.removeAll(col);
System.out.println(coll);
//10.retainAll(Collection col);
//求两个集合的交集,并返回给coll
System.out.println(coll.size());
Collectioncol=Arrays.asList(123,1245);
coll.retainAll(col);
 
//11.equals(Collection col);
//boolean
Collectioncoll1=newArrayList();
coll1.add("AA");
coll1.add(newString("bb"));
coll.equals(coll1);
//12.hashcode();
System.out.println(coll.hashCode());
//13.toArray();
//集合变成数组
System.out.println(coll.size());
Object[] obj=coll.toArray();
System.out.println(obj[0]);
//拓展:数组到集合::Arrays.asList(newString[]{"11","22","33"});
//14.iterator():返回Itetator接口的实例,用于遍历集合元素。
 

 

2 Interator接口遍历Collection

//迭代器接口,用来遍历集合:提供了一种方法访问一个集合对象中各个元素,又不需要暴露该对象的内部细节

Iterator iterator = coll.iterator();

System.out.println(iterator.next());

//hasNext()

while(iterator.hasNext()){

System.out.println(iterator.next());

}

注意:每调一次,coll.iterator()方法都会生成一个新的迭代器

 

---->迭代器中的remove()方法:先 ierator.next(),在iterator.remove()就能删除一个元素

 

3 增强for循环

foreach---->for(Object obj : coll){ }

 

4 Collection子接口 List

---->动态数组

---->ArrayList / LinkedList / Vector三者异同

>三个类都是实现了List接口、存储的数据都是 有序的、可重复的

>不同:

>ArrayList:作为List接口的主要实现类,JDK1.2;线程不安全、执行效率高。底层使用Object[]存储。

>LinkedList:对于频繁的插入和删除操作,用这个比arrayList效率高;底层用双向链表存储。

>Vector:作为List接口的古老实现类, JDK1.0;线程安全,效率低,底层使用Object[]存储。

 

5 ArrayList底层源码分析(JDK7 / JDK8不一样)

*ArrayList源码分析

*1.1JDK7框架下

*ArrayListlist=newArrayList();//底层创建了一个长度10Object[]的数组elementData

*list.add(123);//elementData[0]=newInteger(123);

*//当某次添加,导致底层elementData数组容量不够,则扩容,默认扩容为原来容量的1.5

*//同时需要将原有数组的数据copy到新数组中。elementData=Arrays.copyOf(elementData)

*

*结论:开发中建议使用带参的构造器

*ArrayListlist=newArrayList(initialCapacity)

*1.2JDK8框架下的变化

*ArrayListlist=newArrayList();

*//底层Object[]elementData初始化为{},并没有创建长度为10的数组

*list.add(123);

*//第一次调用add()时,底层才创建了长度为10的数组

*//后续和JDK7一样

 

6 LinkedList源码分析

*LinkedList源码分析

*LinkedListlist=newLinkedList();

*//内部声明了Node类型的firstlast属性,默认值为null

*list.add(123);//123封装到Node中,创建了Node对象

*

*Node定义为://可以看出LinkedList是双向的

*private static class Node<E>{

*      E item;

*    Node<E> next;

*       Node<E> prev;

*

*       Node(Node<E>prev,Eelement,Node<E>next){

*           this.item=element;

*           this.next=next;

*           this.prev=prev;

*       }

*}

7 Vector源码分析

---->源码中都是同步方法

---->通过无参构造器创建对象时,都创建了大小是10的数组,add后扩容不太一样

 

8 List接口的常见方法

//1.void add(intindex,Objectobj)

//index后面的往后移

list.add(1,"BB");

System.out.println(list.toString());

//2.void addAll(int index,Collectioncol);

Listlist1=Arrays.asList(1,2,3);

list.addAll(3,list1);

System.out.println(list.toString());

//3.Object get(intindex)

System.out.println(list.get(3));

//4.int indexOf(Objectobj)

//返回obj在集合中首次出现的位置

System.out.println(list.indexOf(468));

//5.int lastIndexOf(Objectobj)ni

//返回obj在集合中最后一次出现的位置

System.out.println(list.lastIndexOf(468));

//6.Object remove(intindex)

//移除指定index位置上的元素,并返回次元素

System.out.println(list.remove(4));

//7.Object set(intindex,Objectelc)

//替换指定index位置上的元素为elc

list.set(0,1234);

System.out.println(list);

//8.List subList(intfromIndex,inttoIndex):左开右闭

//返回fromIndex到toIndex位置上的子集合

 

总结常用方法

>增:add(Object obj)

>删:remove(int index) / remove(Object obj)

>改:set(int index, Object obj)

>查:get(int index)

>插:add(int index, Object obj)

>长度: size()

>遍历: Iterator / foreach

 

10 面试题

add(Object obj)方法没有重载方法,因此,add(2)里面2会自动装箱,而remove存在重载,则,2会倾向于直接的int index,不会自动装箱

 

11 set接口

---->无序的、不允许包含相同的元素

---->Set接口:存储无序的、不可重复的数据 ---->数学意义上的”集合“

>HashSet:作为Set接口的主要实现类,线程不安全,效率高,,底层其实是hashmap

>LinkedHashSet:HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历

>TreeSet:可以按照添加的对象的指定属性,进行排序

---->无序的不可重复的 理解:

>无序性:Set set = new HashSet();

>不等于随机性

>存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据Hashcode

>不可重复性:

>保证添加的元素按照equals()判断时,不能返回true,

 

---->Set中添加元素的过程,HashSet为例

>hashSet中既有数组,也有链表

>向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算a的哈希值,此哈希值通过某种算法得到元素a在HashSet底层数组中的存在位置,判断数组在此位置上是否有元素:

如果没有元素,添加成功---->情况1

如果有元素b(或者以链表形式存在的多个元素),则先比较元素之间的hashcode

如果hashcode不同:则a添加成功。---->情况2

如果相同,则调用a的equals()方法,

equals返回true,添加失败

equals返回false,添加成功 ---->情况3

 

对于情况2 和 情况3. 元素a和已经存在的元素以链表形式存在

JDK7,元素a放在数组中,指向原来的元素

JDK8,原来的元素在数组中,指向a

 

12 LinkedHashSet

 

13 TreeSet

*1.TreeSet中添加的元素必须是同一类的

*2.两种排序方式:自然排序(实现comparable/定制排序(实现Comparator接口)

*3.自然排序中,比较两个对象是否相等的标准是,comparable()0,不再用equals()

*4.定制排序中,比较两个对象是否相等的标准是,compare()0,不再用equals()

 

14 练习题

---->利用Set对List中的重复数值进行删除

 

---->p1.setName("cc")之后 p1的hash值已经变了,在进行remove操作时,用新的hash值和老的hash比较

 

15 Map接口

---->Map:接口,存储 键值对 key - value,类似于函数

---->HashMap:作为Map的主要实现类,线程不安全;可以存储null的key和value

---->LinkedHashMap:保证在遍历map的时候,可以按照添加时候的顺序来遍历

---->TreeMap: 保证可以按照添加的key - value对进行排序,实现排序遍历,考虑key的自然排序和定制排序

底层用的是红黑树

---->Hashtable:Map的古老实现类,线程安全;不能存储null的key和value

---->Properties:常用来处理配置文件,,key和value都是String

 

HashMap的底层:数组+链表(JDK7以前)

数组+链表+红黑树(JDK8以后)

 

面试题:

1. HashMap的底层实现原理:

2.HashMap 和Hashtable 的异同?

 

16 Map中key-value的理解

---->key是无序的,不能重复的 ,用set存储  |---->key所在的类需要重写equals和hashcode方法

---->value是无序的,可重复的 ,用collection存储  |---->value所在的类需要重写equals

---->一个key-value构成一个Entry对象,无序,不可重复,用set存储

 

17 HashMap的底层实现原理

//以下是基于JDK7

HashMap map = new HashMap();

实例化之后,底层创建了一个长度是16的一维数组:Entry[] table

map.put(key1, value1);

首先,调用key1的hashCode()方法,得到key1的hash值,此哈希值经过一定的运算,得到在Entry数组中的存放位置

如果,此位置上没有数据,则此时key1-value1添加成功  ---->情况1

如果,此位置上不为空(一个或多个数据以链表形式存在),则比较key1和其他数据的哈希值

如果,哈希值不同,则key1-value1添加成功  ---->情况2

如果,key1的哈希值,和某个已经存在的数据的key的哈希值相同,则调用key1.equals(key2)

如果,equals()返回false,则添加成功  ---->情况3

如果,equals()返回true,则用key1替换key2

说明: 对于情况2和情况3,此时,key1-value1和已经存在的数据以链表形式存在

遇到扩容的问题是,当超过临界值(且要存放的位置非空)时,扩容为原来的2倍,将原来的数据复制过来

//JDK8中的区别

1.new HashMap()的时候,底层没有创建一个长度为16的数组

2.底层的数组是Node[],而不是Entry[]

3.首次使用put()方法是,底层创建长度16的数组

4.JDK7底层的结构是:数据+链表,JDK8底层结构:数组+链表+红黑树

当数组的某一个位置上的元素以链表形式存在的个数>8,且数组长度>64时,

此时此索引位置上的数据改为红黑树存储

 

 

18 LinkedHashMap底层实现原理‘

 

19 Map的常用方法

总结:常用方法

>添加 Object put(Objdect key, Object value)

>产出 Object remove(Object key)

>修改 Object put(Objdect key, Object value)

>查询 Object get(Object key), 返回value

>长度,size()

>遍历 keySet() / values() / entrySet()

 

20 TreeMap

---->想TreeMap中添加key-value,要求key是同一类型的对象

---->按照key进行,自然排序 / 定制排序

---->comparable / comparator

 

21 Properties

---->常用来处理配置文件,,key和value都是String

 

22 Collections工具类

---->是一个操作Set List Map的工具类

---->Collectios类中提供了多个synchronizedXxx()方法,该方法可使得 指定集合包装成同步的集合,从而可以解决多线程并

     发访问集合是的线程安全问题

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值