Java集合

**

1.集合和数组的同异

**

(1)同:都可以存储多个对象,对外作为一个整体存在
(2)异:
①数组:

1)数组的长度必须在初始化时指定,且固定不变
2)数组中存放基本数据类型或引用数据类型
3)数组存放数据类型,一旦确定就只能操作相同的数据类型对象
4)数组无法判断其中实际存有多少元素,length只告诉了Array的容量
5)数组的存储结构是有序,可重复
6)数组采用连续存储空间,删除和添加效率低下
7)数组缺乏封装,操作繁琐

②集合

1)集合的容量动态
2)集合存放引用数据类型
3)集合支持无序,有序,可重复,不可重复
4)集合支持key-Value键值对的形式
5)集合以类的形式存在,具有封装,继承,多态等类的特性,通过简单的方法和属性调用即可实现各种复杂的操作,大大提高软件的开发效率
**

2.Java集合框架

在这里插入图片描述

在这里插入图片描述

(1)Java中提供了接口和类,位于java.util包中
(2)Collection提供了对集合进行排序,遍历等算法实现
(3)Collection接口存储一组不唯一,无序的对象
(4)List接口存储一组不唯一,有序(插入顺序)的对象
(5)ArrayList实现了长度可变的数组,在内存中分配连续的空间,遍历和随机访问效率高
(6)LinkedList采用链表存储方式。插入,删除效率高
(7)Set接口存储一组唯一,无序的对象
(8)Map接口存储一组键值对象,提供key到value的映射

3.Collection——单列集合

(1)Collection是接⼝,不能直接创建对象
(2)Collection 接⼝是List、Set,该接⼝⾥定义的⽅法既可⽤于操作Set 集合,也可用于操作List集合
(3)创建方式

因为接口不能直接实例化,那么就实现他的实现类:Collection c = new ArrayList();

(4)没有get方法
(5)常用方法

· ①添加

add():添加单个元素
addAll():添加元素的集合
1)在集合中添加引用数据类型时直接添加
2)在集合中添加基本数据类型时,会添加对应的包装类(自动转换为包装类,自动装箱)

· ②获取有效元素的个数

size()

· ③清空集合

clear();

· ④判断是否是空的集合

isEmpty();

· ⑤判断是否包含某个元素

contains 通过equals来比较是不是同一个元素

(在使用contains 进行比较时,也可以通过重写equals方法实现类的对象的属性的比较。因为contains 判断的时传入对象的equals方法,equals为true返回true)
containsAll 通过调用元素的equals来挨个比较

· ⑥删除

remove
removeAll

· ⑦遍历

Iterator——有个游标,遍历时自动加一

· (6)Collection 遍历方式

①第一种遍历方式——使用迭代器iterator
1)Iterator iterator = new iterator();————也可以等于集合对象 . iterator()
System.out.println(iterator.next);

2)for(int i = 0; i<c.size();i++){
	System.out.println(iterator.next);
	
3)hasNext()会判断当前位置是否有元素
		while(iterator.hasNext()){
		System.out.println(iterator.next);
}
②第二种遍历方式——增强型for循环:foreach遍历
for( 要遍历的元素类型 遍历后自定义元素名称 : 要遍历的结构名称){
	System.out.println(遍历后自定义元素名称 . getName());——或者直接输出遍历后自定义元素					名称 
}

4.List

(1)List集合类中元素有序,可重复,集合中的每个元素都有其对应的顺序索引
(2)JDK.API中List接口的实现类常用的有:ArrayList,LinkedList,Vector
(3)在各种list中,最好把ArrayList作为缺省(默认)选择。当插⼊、删除频繁时,使⽤LinkedList,Vector总是⽐ArrayList慢, 所以尽量避免使⽤。
(4)List接口常用方法
Boolean add (Object o)	在列表的末尾顺序添加元素,起始索引位置从0开始

Void add (int index , Object o)	在指定的索引位置添加元素,索引位置必须介于0和列表中元素个数之间

int size()	返回列表中的元素个数

Object get (int  index)	返回指定索引处的元素,取出的元素是Object类型,使用前需要进行强制类型转换

Object set (int  index ,Object o )	修改指定索引位置上的元素

Boolean contains(Object o)	判断列表中是否存在指定元素

Boolean remove(Object o)	从列表中删除元素

Object remove (int index)	从列表中删除指定位置元素,起始索引位置从0开始

list.clear	清空

list.isEmpty()	判断是否为空

list.toArray(new  String [list.size()])	将list集合转换成String数组

5.ArrayList

(1)有序,可重复,
(2)作为List接⼝的主要实现类;
(3)线程不安全的,效率⾼;
(4)底层使⽤Object[] elementData存储
(5)ArrayList是对象引⽤的⼀个”变⻓”数组
①JDK7之前:ArrayList list = new ArrayList();//底层创建了⻓度是10的Object[]数组elementData
②JDK8之后:ArrayList list = new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度 为10的数组。比如list.add(123);//第⼀次调⽤add()时,底层才创建了⻓度10的数组,并将数据123添加到elementData[0]
(6)ArrayList的扩容机制

ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。(不是原数组,⽽是新数组然后给予数组对象地址)。新的数组容量=旧的数组容量+旧的容量/2

(7)ArrayList遍历
①迭代器遍历
    Iterator iterator = arrayList.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
②增强for循环遍历
    for (Object o:arrayList) {
 		System.out.println(o);
    }
③for遍历
    for (int i = 0; i < arrayList.size(); i++) {
		System.out.println(arrayList.get(i));
    }
(8)将list集合转换成String数组
Object[] objects = arrayList.toArray(new Object[arrayList.size()]);
(9)将String数组转换成list集合
Object [] arr = new Object[10];
List<Object> objects1 = Arrays.asList(arr);

6.LinkedList

(1)对于频繁的插⼊或删除元素的操作,建议使⽤LinkedList类,效率较⾼。
(2)LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的First和Last用于记录首末元素,同时,定义内部类Node,作为LinkedList中保存数据的基本结构
(3)元素的数据类型
Prev	data	next
(4)特殊方法
void addFirst(Object o)	在列表的首部添加元素

void addLast(Object o)	在列表的尾部添加元素

Object getFirst()	返回列表中的第一个元素

Object getLast()	返回列表中的最后一个元素

Object removeFirst()	删除并返回列表中的第一个元素

Object removeLast()	删除并返回列表中的最后一个元素

7.ArrayList和LinkedList的联系和区别

(1)联系:都实现了List接口,都是有序,不唯一(可重复)
(2)区别
①ArrayList:在内存中分配连续的空间,采用了顺序表结构,实现了长度可变的数组
a.优点:遍历和随机访问效率高
b.缺点:删除和添加需要大量移动元素,效率低,按照内容查询效率低
②LinkedList:采用链表存储方式
a.优点:插入,删除效率高
b.缺点:遍历和随机访问效率低

8.Vector

(1)Vector 是⼀个古⽼的集合,JDK1.0就有了。⼤多数操作与ArrayList相同,区别之处在于Vector是线程安全的
(2)jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了⻓度为10的数组。
(3)在扩容⽅⾯,默认扩容为原来的数组⻓度的2倍

9.Vector和ArrayList的联系和区别

(1)联系:实现原理相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
(2)区别:
①Vector 是早期JDK接口,ArrayList是替代Vector 的新类
②Vector 线程安全,ArrayList重速度轻安全,线程不安全

10.Set

(1)Set接口相对Collection没有增加任何⽅法
(2)无序(底层使用哈希函数计算出每一个元素的哈希值,根据哈希值进行存储,所以无序)
(3)不可重复(底层用的是equals方法,对存储的元素进行判断,先走hashcode方法,如果哈希值一样,会走equals方法)
(4)如果要存储自定义类,因为创建的是对象,所以对象的属性一样也可以存进去,如果要实现唯一,要重写hashcode方法
(5)Set 集合不允许包含相同的元素,如果试把两个相同的元素加⼊同⼀个Set 集合中,则添加操作失败。
(6)Set的遍历⽅法
①第一种遍历——增强型for循环:foreach遍历
②第二种遍历——使用迭代器iterator
③⽆法使⽤for进⾏遍历,因为⽆序,所以没有get(i)

11.HashSet

(1)作为Set接⼝的主要实现类,是线程不安全的,可以存储null值(但只能存储一个)
(2)自定义的类存储在HashSet中如果要想唯一(不重复),必须重写HashCode和equals方法
(3)添加元素的过程——add
①先去取存⼊对象的hash值,调⽤的是hashCode⽅法
②通过计算hash值来确定存放在hashSet底层数组的⼀个位置(索引),导致内容就是⽆序的
③判断当前位置上是否有元素
1)如果没有元素 :那就直接添加数据
2)如果有: 先去⽐较hash值
a.如果hash值不同:添加成功,在指定索引上 以链表的形式进⾏存储
b.如果hash值相同:
	a)⽐较equals⽅法
		i.如果返回false :添加成功 以链表的形式进⾏存储
		ii.如果返回true:添加失败 证明是同⼀个元素
(4)每一个索引位置上有一个单链表,把相同索引的元素链接起来
(5)常用方法
add(E  e)	如果此set中尚未包含指定元素,则添加指定元素

Clear()	从此set中移除所有元素

contains(Object  o)	如果此set中包含指定元素,返回true

isEmpty()	如果此set中不包含任何元素,返回true

iterator()	返回对此set中元素进行迭代的迭代器

size()	返回此set中的元素的数量(set的容量)

remove(Object  o )	如果指定元素存在于此set中,则将其移除

12.TreeSet

(1)有序(自然顺序),唯一,常用方法和HashSet一样
(2)TreeSet存储结构:二叉树(红黑树)
(3)可以按照添加对象的指定属性,进⾏排序——⾃然排序,定制排序
(4)不能添加不同的类的对象
(5)TreeSet要存储自定义类必须要实现Comparable接⼝(内部比较器),重写compareTo⽅法——⾃然排序。或者创建实现Comparator接口的类(外部比较器)。外部比内部的优先级要高
(6)Comparable⾃然排序

在这里插入图片描述

(7)Comparator定制排序

在这里插入图片描述

(8)Comparable和Comparator的区别
①当元素的类型没有实现java.Lang.Comparable接口而又不方便修改代码,或者实现了java.Lang.Comparable,但接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
②对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(Object obj)
③compare( Object o1 , Object o2 )是int类型包装类的方法,比较传入的两个值,前者大于后者返回正整数,前者小于后者返回负整数,前者等于后者返回0
④compareTo( Object obj )是String类型的方法,用当前对象的this和传入的形参obj比较,this大于obj返回正整数,this小于obj返回负整数,this等于obj返回0

13.LinkedHashSet

(1)有序(添加顺序),唯一,速度快,是哈希表+链表,常用方法和HashSet一样
(2)他是HashSet的⼦类,LinkedHashSet插⼊性能略低于HashSet
(3)有Hash表,要存储自定义类,并且保持唯一(不重复),也要重写HashCode和equals方法
(4)LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使⽤双向链表维护元素的次序,这使得元素看起来是以插⼊顺序保存的。——插入乱序,输出有序

14.Map——双列集合

(1)Map存储双列数据,存储key-value对,⼀个键值对:key-value构成了⼀个Entry对象
(2)Map的数据结构:Map的key是⽆序的,不可重复的, 使⽤Set存储所有的key。value是⽆序的、可重复的,使⽤Collection存储所有的value。entry是⽆序的、不可重复的,使⽤Set存储所有的entry
(3)HashMap——作为Map的主要实现类;线程不安全的,效率⾼;可以存储null的key和value
(4)HashMap的底层——(jdk7及之前)数组+链表 (jdk 8)数组+链表+红⿊树
(5)LinkedHashMap——保证在遍历map元素时,可以按照添加的顺序实现遍历。
(6)TreeMap ——保证按照添加的key-value对进⾏排序,实现排序遍历。此时考虑key的⾃然排序或定制排序。底层使⽤红⿊树
(7)Hashtable ——作为古⽼的实现类;线程安全的,效率低;不能存储null的key和value
(8)常用方法
Object  put(Object  key , Object  val)	以键值对的方式进行存储

Object  putAll(Map  m)	将map中的所有键值对存放到当前的map中

Object  get(Object  key )	根据键返回相关联的值,如果不存在,返回null

Object  remove(Object  key )	删除由指定的键映射的键值对

int  size()	返回元素个数

Set  keySet()	返回键的集合

Collection  values()	返回值的集合

Set   entrySet()	返回所有key-value对构成的set集合

boolean containsKey(Object  key)	是否包含指定的key,是返回true

boolean containsValue(Object  value)	是否包含指定的vlaue ,是返回true

boolean   isEmpty()	判断当前map是否为空

boolean   euqals((Object  obj)	判断当前map和参数对象obj是否相等

void  clear()	清空当前map中的所有数据
(9)遍历
①拿到所有的Key,循环去获取对应的value
Set set = map.keySet();
for (Object o:set ) {
     Object o1 = map.get(o);
     System.out.println(o);
     System.out.println(o1);      
}
②遍历values
Collection values = map.values();
Iterator iterator = values.iterator();
while (iterator.hasNext()){
    System.out.println(iterator.next());
}
③遍历entryset集合
 Set<Map.Entry> entrySet = map.entrySet();
 for (Map.Entry e:entrySet) {
     Object value = e.getValue();
     Object key = e.getKey();
     System.out.println(key+","+value);
}

15.HashMap

(1)Key——无序,不唯一(HashSet)。Value——无序,不唯一(Collection)
(2)存储数据的过程
①JKD7——数组+链表
1)创建⼀个HashMap时,会先去创建⼀个⻓度为16的,类型为Entry类型的数组
2)当调⽤map.put(k1,v1);⽅法时,会先去计算k1的⼀个哈希值,通过运算确定放在数组具体的什么位置
3)然后判断,数组此位置上是否已经有元素:
	a.如果此位置上没有其他元素,则元素a添加成功。 
	b.如果此位置上有其他元素b(或以链表形式存在的多个元素)
		a)则⽐较元素a与元素b的hash值 
			i.如果hash值不相同,则元素a添加成功。
			ii.如果hash值相同,进⽽需要调⽤元素a所在类的equals()⽅法: 
					i)equals()返回true,则使⽤v1替换掉v2
					ii)equals()返回false,则元素a添加成功。
②JDK8(重点)——数组+链表+红⿊树
1)在new HashMap()时,不去创建⻓度为16的数组
2)数组类型不再是Entry ⽽是Node
3)⾸次调⽤put⽅法时才会去创建⻓度为16的数组
4)当数组的某⼀个位置上的元素链表超过8个 ,并且当前的数组⻓度>64的时候,此时当前索引位置上的所有数据变为红⿊树存储
(3)HashMap扩容机制
①当HashMap中的元素个数超过数组⼤⼩(数组总⼤⼩length,不是数组中个数size)*loadFactor时就会进⾏数组扩容,loadFactor的默认值(DEFAULT_LOAD_FACTOR)为0.75。
②默认情况下,数组⼤⼩(DEFAULT_INITIAL_CAPACITY)为16,那么当HashMap中元素个数超过160.75=12(这个值就是代码中的threshold值,也叫做临界值)的时候,就把数组的⼤⼩扩展为216=32,即扩⼤⼀倍,然后重新计算每个元素在数组中的位置
③⽽这是⼀个⾮常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数 ,那么预设元素的个数能够有效的提⾼HashMap的性能。
④当HashMap中的其中⼀个链的对象个数如果达到了8个,此时如果capacity没有达到64, 那么HashMap会先扩容解决,如果已经达到了64,那么这个链会变成红⿊树,结点类型由Node变成TreeNode类型。当然,如果当映射关系被移除后, 下次resize⽅法时判断树的结点个数低于6个,也会把红⿊树再转为链表。

16.HashMap和Hashtable的联系和区别

(1)联系:实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用
(2)区别:
①Hashtable是早期JDK类,HashMap是新版JDK提供的类
②Hashtable继承Dictionary类,HashMap实现Map接口
③Hashtable线程安全,HashMap线程非安全
④Hashtable不允许null值,HashMap允许null值

17.TreeMap

(1)唯一,自然有序,底层数据结构是二叉树,速度没有hash快(TreeMap存储Key-Value 对时,需要根据key-value对进⾏排序)。
(2)TreeMap中,Map和Set采用了相同的数据结构,只用于map的key存储数据,就是Set
(3)TreeMap可以保证所有的Key-Value 对处于有序状态
①⾃然排序:
TreeMap的所有的Key 必须实现Comparable接⼝,⽽且所有的Key应该是同⼀个类的对象,否则将会抛出ClasssCastException 
②定制排序:
创建TreeMap时,传⼊⼀个Comparator 对象,该对象负责对TreeMap中的所有key 进⾏排序。此时不需要Map 的Key实现Comparable 接⼝

18.LinkedHashMap

(1)唯一,有序的HashMap(添加的顺序),速度快,是哈希表+链表(针对key)
(2)key -----与LinkedHashSet原理一样

19.Collections——操作集合工具类

(1)构造方法私有,禁止创建对象
(2)提供一系列静态方法实现对各种集合的操作
(3)具体操作:搜索,复制,排序,线程安全化等
(4)常用方法
Shuffle	随机排序

sort	自然排序按升序排序

sort(List  list , Comparator  c)	自定义排序,由Comparator来制定排序的逻辑

swap(List  list  ,int  i, int  j )	交换指定索引位置的元素

int  max(Collection  coll ,Comparator c) 	根据自定义排序,返回最大值

int  max(Collection  coll)   	根据自然排序,返回最大值

int  min(Collection  coll)   	根据自然排序,返回最小值

void fill(List  list , Object  obj)	用指定元素代替指定list中的所有元素

bollean  replaceAll	替换所有元素

int  binarySearch(List  list , Object  key)	二分查找,返回索引值,前提有序

添加	Collections.addAll(list, "aaa","bbb","ccc","ccc");

反转指定列表中元素的顺序	Collections.reverse(list4);

线程安全	List list5 = Collections.synchronizedList(list4);

20.Collection和Collections的区别

(1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。他有两个子接口List和Set
(2)Java中还有一个Collections类,专门用于操作集合类,它提供了一系列静态方法实现对各种集合的搜索,排序,线程安全化等操作

21.泛型

(1)为什么要用泛型:
①JDK1.4以前类型不明确:装入集合的类型都被当作Object对待,从而失去自己的实际类型,从集合中取出时往往需要转型,效率低,容易产生错误。
(2)泛型是在定义集合的时候同时定义集合中对象的类型,可以增强程序的可读性和安全性
(3)Java泛型中的标记符含义
①E - Element (在集合中使用,因为集合中存放的是元素)
②T - Type(Java 类)
③K - Key(键)
④V - Value(值)
⑤N - Number(数值类型)
⑥? - 表示不确定的java类型

22.迭代器Iterator

(1)Iterator是迭代器设计模式的具体实现
(2)所有集合类均未提供相应的遍历方法,而是把把遍历交给迭代器完成。迭代器为集合而生,专门实现集合遍历
(3)哪些类可以使用Iterator进行遍历
List		Set		Collection
只有直接或间接的实现了Iterator接口的接口或者类才可以使用Iterator进行遍历
(4)Iterator方法
①boolean hasNext()——判断是否存在另一个可以访问的元素
②Object next()——返回要访问的下一个元素
③void remove()——删除上次访问返回的对象
④在使用for-each循环和Iterator遍历集合时,不能通过集合对象直接删除元素,可以通过it.remove()删除当前元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值