什么是集合
集合类存放于java.util包中。
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)。
集合类型主要有3种:set(集)、list(列表)和map(映射)。
通俗的说,集合就是一个放数据的容器,准确的说是放数据对象引用的容器。
Java集合类
集合主要分为Collection和Map2个接口
Collection又分别被List和Set继承
List被AbstractList实现,然后分为3个子类,ArrayList,LinkList和Vector
Set被AbstractSet实现,又分为HashSet和TreeSet
而Map衍生出的集合分为HashMap,HashTable和TreeMap
Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构如下:
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet
List:接口,允许出现重复元素。与Set另一个不同的地方就是元素有序。如果你对加进‘罐子’里东西很在乎先后。如谁先进去的谁后进去的,第几个是谁比较关心可以选用。但是同样。List是个接口我们通常使用的是两个实现了该接口的两个类arrayLis和LinkedList。
ArrayList:支持对元素的快速访问。但是对插入和删除支持性差。
LinkedList: 对元素的插入和删除性能良好。由于List中元素有序,可以我们不用Iterator对象也可以访问,不过要先调用toArray()方法。才能像操作一个普通数组一样访问。
Set:是一个接口,无序集合,不能包含重复元素。同时身为接口不能生成对象。但是类HashSet和TreeSet实现了该接口,所以通常使用的也是这两个。
HashSet:该集合中主要存放的一些无序元素。如果你只是想用一个‘罐子’盛东西,其他什么都不关心,可以选它。
TreeSet:该集合除了实现Set接口还实现了SortedSet接口。也就是说可以用它来进行一些排序默认升序。当然排序的元素必须具有可比性。也就是说对于基本类型如:Float, Integer,String,Character等
Map: 接口,相当于映射。每个项都是成对的。映射中存储的每个对象都有一个相关的关键字(Key)对象,关键字决定了 对象在映射中的存储位置,检索对象时必须提供相应的关键字,就像在字典中查单词一样。关键字应该是唯一的。
关键字本身并不能决定对象的存储位置,它需要对过一种散列(hashing)技术来处理,产生一个被称作散列码(hash code)的整数值,
散列码通常用作一个偏置量,该偏置量是相对于分配给映射的内存区域起始位置的,由此确定关键字/对象对的存储位置。理想情况 下,散列处理应该产生给定范围内均匀分布的值,而且每个关键字应得到不同的散列码。
集合特点:
(1) Collection(单列集合)
List(有序,可重复)
ArrayList 底层数据结构是数组,查询快,增删慢 线程不安全,效率高
Vector 底层数据结构是数组,查询快,增删慢 线程安全,效率低
LinkedList 底层数据结构是链表,查询慢,增删快 线程不安全,效率高
Set(无序,唯一)
HashSet 底层数据结构是哈希表。 哈希表依赖两个方法:hashCode()和equals()(一般规则:对象equals 是true的话,hashCode需要相同,但是hashCode相同的对象不一定equals,这就是所谓的冲突现象,但是有不同的冲突解决方法。你的hashCode()设计的好的话冲突也就小了。比如楼上给出的超出int范围之后这种hashCode()实现,对象肯定是无数的,但是hash实现是有限的呢,所以冲突了。)
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:自动生成hashCode()和equals()即可
LinkedHashSet 底层数据结构由链表和哈希表组成。 由链表保证元素有序。 由哈希表保证元素唯一。
TreeSet 底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢? 根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性) 让元素所属的类实现Comparable接口
比较器排序(集合具备比较性) 让集合接收一个Comparator的实现类对象
(2)Map(双列集合)
A:Map集合的数据结构仅仅针对键有效,与值无关。
B:存储的是键值对形式的元素,键唯一,值可重复。
HashMap
底层数据结构是哈希表。线程不安全,效率高 哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终: 自动生成hashCode()和equals()即可
LinkedHashMap 底层数据结构由链表和哈希表组成。 由链表保证元素有序。 由哈希表保证元素唯一。
Hashtable 底层数据结构是哈希表。线程安全,效率低 哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终: 自动生成hashCode()和equals()即可
TreeMap
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢? 根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性) 让元素所属的类实现Comparable接口
比较器排序(集合具备比较性) 让集合接收一个Comparator的实现类对象
集合使用
到底使用那种集合: 看需求。
是否是键值对象形式:
是:Map
键是否需要排序: 是:TreeMap 否:HashMap 不知道,就使用HashMap。
否:Collection
元素是否唯一:
是:Set
元素是否需要排序: 是:TreeSet 否:HashSet 不知道,就使用HashSet
否:List
要安全吗:
是:Vector(其实我们也不用它,后面我们讲解了多线程以后,我在给你回顾用谁)
否:ArrayList或者LinkedList
增删多:LinkedList 查询多:ArrayList 不知道,就使用ArrayList
不知道,就使用ArrayList