集合框架:
数组和集合的区别:
3个方面:
1长度
数组:不可变 集合:可变
2内容
数组:内容必须为同一数据类型;
3元素类型
数组:元素可以是基本数据类型,和引用数据类型。
集合:只能是引用数据类型。
Collection:
Collection接口概述 :
Collection 层次结构中的根接口。
Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。
Collection接口成员方法
添加功能:
boolean add(E e) :添加一个元素
Boolean addAll(Collection c):添加一个集合的元素。(所有元素都添加,相同的元素不能添加)
删除功能:
void clear():移出所有元素。
Boolean remove(object o):移出一个元素。
Boolean removeAll(collection c):移出一个集合的元素(只要集合中有一个元素移除了,就返回true)
判断功能
Boolean contains():判断集合中是否包含指定的元素。
注意:contains()底层依赖于equals()方法,当使用对象调用该方法的时候,需要重写equals()方法,不然的话,就默认调用的object的equals()方法,比较的是地址。
boolean containsAll(collection c):判断集合中是否包含指定的集合元素(包含所有的元素,才能叫做包含)
Boolean isEmpty():判断集合是否为空。
获取功能
Interator<E> iterator()迭代器,集合的专用遍历方式
交集功能
Boolean retainAll(collection c):两个集合都有的元素()
A和B两个集合。A和B交集,最终的结果保存在A中,B不变。
返回值表示A是否发生过改变。
集合转数组
object[] toArray()把集合转成数组,可以实现集合的遍历
iterator iterator ():迭代器,集合的专用遍历方式
List接口
概述:
有序的 collection(也称为序列)。
此接口的用户可以对列表中每个元素的插入位置进行精确地控制。
用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
与 set 不同,列表通常允许重复的元素。
list集合才有普通for循环
成员方法:
void add(int index,E element):在指定位置添加元素。
E remove(int index) :删除指定位置的元素,返回被删除的元素。
E get(int index) :得到指定索引处的元素。
E set(int index,E element) :根据索引修改元素,返回被修改的元素(你把谁删了)
ListIterator listIterator() :
list特有的迭代器。继承了Iterator迭代器。可以直接使用hasNext()和next()方法。
特殊方法:
boolean hasPrevious() :判断是否有元素。
E previous() :返回上一个元素,并且把指针向前移动。
注意:ListIterator可以实现逆向遍历,但是必须是先正向遍历,才能逆向遍历,所以一般无意义,不使用。
ConcurrentModificationException 并发修改异常
原因:迭代器遍历元素的时候,通过集合是不能修改元素的,如果进行了了修改,就会抛出该异常。
迭代器是依赖于集合存在的,在判断成功后,集合中新添加了元素,而迭代器不知道,所以就报错了。
如果想要修改解决方案:
第一种:迭代器迭代元素, 迭代器修改元素。
添加的元素是跟在刚才迭代的元素后面的。
Iterator中没有添加功能,所以使用期子接口ListIterator中的添加功能。
第二种:集合遍历元素,集合修改元素(普通for)。
元素是在最后添加的。
list的子类的特点(面试题)
ArrayList:
底层数据结构是数组,查询快,增删慢。
不同步,线程不安全,但是效率高。
Vector:
底层数据结构是数组,查修快,增删慢。
同步,线程安全,但是效率低。
LinkedList:
底层数据结构是链表,查询慢,增删快。
不同步,线程不安全,但是效率高。
vector的特有方法:
public void addElement(object o):添加功能。被add替代
elementAt(int index);获取功能;被get(),替代。
public Eumeration elements();被Iterator Iterator()替代
LinkedList类特有方法:
添加:
public void addFirst(E e)添加到第一个
addLast(E e) 添加都最后
获取:
public E getFirst():得到第一个
getLast() :得到最后一个
移出:
public E removeFirst():删除第一个,返回删除的元素。
public E removeLast() :删除最后一个,返回删除的元素。
面试题:使用LinkedList模拟栈数据结构集合,并且测试;
Set接口
概述:一个不包含重复元素的 collection。元素是无序的,唯一的(不可以使用普通for循环遍历)
注意:虽然存储顺序无序,但是作为集合,有自己的存储顺序。
HashSet类
概述
不保证 set 的迭代顺序
特别是它不保证该顺序恒久不变。
HashSet如何保证元素唯一性
底层数据结构是哈希表(元素是链表的数组)
哈希表依赖于哈希值存储
添加功能(add()),调用的hash数据结构,保证唯一性的底层依赖调用对象的两个方法: (这两个方法在对象中均可直接快速生成!)
int hashCode()
boolean equals(Object obj)
LinkedHashSet类(HashSet子类)
概述
元素有序唯一
由链表保证元素有序 (进入和取出的顺序一致)
由哈希表保证元素唯一
TreeSet类(底层是TreeMap)
概述 :能够对元素按照某种规则进行排序(目前主要有2种排序方式,具体使用哪一种取决于使用的构造方法。)
自然排序:使用元素的自然顺序对元素进行自然排序(无参构造)
注意:如果一个对象的元素想要进行自然排序,就必须实现comparable接口,并且重写compareTo方法。
并且要知道主要排序条件。
比较器排序:或者根据创建 set 时提供的 Comparator 进行排序 。(代参构造)
TreeSet是如何保证元素的排序和唯一性的?
唯一性:根据比较的返回是否为0来决定
排序:
自然排序(元素具备比较性)
比较器排序(集合具备比较性)
底层数据结构是红黑树(红黑树是一种自平衡的二叉树)
Map集合接口
概述
将键映射到值的对象
一个映射不能包含重复的键 ,并且是无序的。
每个键最多只能映射到一个值
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的,,无序的 ,List是可以重复的。
Map集合的数据结构值针对键有效,跟值无关
Collection集合的数据结构是针对元素有效
Map接口成员方法
添加功能:
V put(K key,V value):添加以及替换功能。建相同,值覆盖。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存储,就用传入的值把之前该键的值替换掉,返回被替换的元素。
删除功能:
void clear():删除所有键值对元素。
V remove(Object key):根据键删除键值对元素,并把值返回。
判断功能:
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty(): 判断集合是否为空。
获取功能:
V get(Object key) :根据键获取值,如果键不存在则,返回null。
Set<K> keySet() :获取集合中所有的键的集合。
Collection<V> values() :获取集合中所有值的集合。
Set<Map.Entry<K,V>> entrySet() :返回的是键值对对象的集合。Entry(实体)
长度功能:
int size():返回集合中的键值对的对象。
Map集合遍历:
方式1:根据键找值
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
方式2:根据键值对对象找键和值
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
HashMap类
概述 键是哈希表结构,可以保证键的唯一性 (唯一性:底层依赖对象:int hashCode() boolean equals(Object obj) )
HashMap案例
HashMap<String,String>
HashMap<Integer,String>
HashMap<String,Student>
HashMap<Student,String>
LinkedHashMap类概述
Map 接口的哈希表(唯一性)和链接列表(有序(添加和取出的顺序一致))实现,具有可预知的迭代顺序。
TreeMap类概述
键是红黑树结构(二叉树唯一并且排序),可以保证键的排序和唯一性 ;
排序和唯一性两种实现方式:自然排序和比较器排序(见TreeSet)
面试题:
HashMap和Hashtable的区别
Hashtable:同步,线程安全,效率低,不允许null键和null值。
HashMap:不同步,线程不安全,效率高,允许null键和null值。
List,Set,Map等接口是否都继承自Map接口 你常见的集合类有哪些,都有什么方法?
list和set继承collection接口。
Map接口本身是一个顶层接口。
Collections类概述 针对集合操作 的工具类
与Collection区别:
Collection:是单列集合的顶层接口,有子接口list和set。
Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法。
Collections成员方法
public static <T> void sort(List<T> list) :排序(默认情况下是自然排序)
public static <T> int binarySearch(List<?> list,T key) :二分查找,找到返回元素下标,找不到返回长度+1取反。
public static <T> T max(Collection<?> coll) :最大值
public static void reverse(List<?> list) :翻转
public static void shuffle(List<?> list) :随机置换
1:集合总结(自己补齐)
Collection(单列集合)
List(有序,可重复)
ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低
LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
Set(无序,唯一)
HashSet
底层数据结构是哈希表。
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashSet
底层数据结构由链表和哈希表组成。
由链表保证元素有序。
由哈希表保证元素唯一。
TreeSet
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
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的实现类对象
2:到底使用那种集合
看需求。
是否是键值对象形式:
是:Map
键是否需要排序:
是:TreeMap
否:HashMap
不知道,就使用HashMap。
否:Collection
元素是否唯一:
是:Set
元素是否需要排序:
是:TreeSet
否:HashSet
不知道,就使用HashSet
否:List
要安全吗:
是:Vector(其实我们也不用它,后面我们讲解了多线程以后,我在给你回顾用谁)
否:ArrayList或者LinkedList
增删多:LinkedList
查询多:ArrayList
不知道,就使用ArrayList
不知道,就使用ArrayList
3:集合的常见方法及遍历方式
Collection:
add()
remove()
contains()
iterator()
size()
遍历:
增强for
迭代器
|--List
get()
遍历:
普通for
|--Set
Map:
put()
remove()
containskey(),containsValue()
keySet()
get()
value()
entrySet()
size()
遍历:
根据键找值
根据键值对对象分别找键和值
4:ArrayList,LinkedList,HashSet,HashMap(掌握)
存储字符串和自定义对象数据并遍历
5:集合的嵌套遍历(理解)
增长方式:
Collection:
1.list集合接口:
方法:
-
-
- Int s=List.Size():集合元素长度。没有的话为0
- List.add(object);添加元素
- List.add(index,object);添加元素在index位置,如果该处有元素,则后面的元素依次向后面移动。
- List.Remove(int index);移除下标对应的元素。
- List.Remove(object):移除某个元素。
- List.get(index);获取某个元素。
- List.set(index,object);设置index位置处的元素为object,覆盖之前元素。
- Boolean b=List.isEmpty();判断数组是否为空。
-
-
- Linkedlist:(非同步,双向链表,用于增删)LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项前后项即可,插入数据较快。(LinkedList一样,ArrayList也是非同步的(unsynchronized))
- Vector:(同步)Arraylist和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以插入数据慢,查找有下标,所以查询数据快,Vector由于使用了synchronized方法-线程安全,所以性能上比ArrayList要差。
- Stack:(同步,数组,)线程安全。
- Set:(一个不包含重复元素的 collection,无序的,用于去重);
TreeSet:(有顺序)
HashSet:(无序)
- Map(接口,不属于collection的子接口)
键值对的形式,要求健唯一。
Hashmap:(允许一个null健)
常用方法:
put(key,value),增加内容。
Set(key);通过key,得到值。
KeySet();获取健返回一个set容器(无序,去重)。相当于健的数组.
Hashtable:(不允许null健)
常用方法:
增长方法:
Iterator接口
概述
对 collection 进行迭代的迭代器 依赖于集合而存在
成员方法:
boolean hasNext()
E next() 获取元素,并移动到下一个位置
注意:迭代器真正的具体实现类在具体的集合子类中,以内部类的方式体现的,并且重写了里面的三个抽象方法(
boolean hasNext() ,next(),以及remove())