集合类的由来:
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。
集合特点:
1,用于存储对象的容器。
2, 集合的长度是可变的。
3,集合中不可以存储基本数据类型值。
4.注意集合的嵌套
集合容器因内内部的数据结构不同,有多种具体容器。不断的向上抽取,,就形成ア集合框架。框架的頂屋collection接口:
collectian的常见方法:
框架继承关系:
看上面的框架图,先抓住它的主干,即Collection和Map。Map不是Collection的子接口,这个要牢记。
1、Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。Collection包含了List和Set两大分支。
(1)List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。List的实现类有LinkedList, ArrayList, Vector, Stack。
(2)Set是一个不允许有重复元素的集合。Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。
2、Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。AbstractMap是个抽象类,它实现了Map接口中的大部分API。而HashMap,TreeMap,WeakHashMap都是继承于AbstractMap。Hashtable虽然继承于Dictionary,但它实现了Map接口。
3、接下来,再看Iterator。它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现iterator()函数,返回一个Iterator对象。ListIterator是专门为遍历List而存在的。
4、再看Enumeration,它是JDK 1.0引入的抽象类。作用和Iterator一样,也是遍历集合;但是Enumeration的功能要比Iterator少。在上面的框图中,Enumeration只能在Hashtable, Vector, Stack中使用。
5、最后,看Arrays和Collections。它们是操作数组、集合的两个工具类。
获取 :
Int size() :
Iterator itarator ():取出元素的方式:迭代器。
垓対象必須依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的。
对于便用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的対象即可,也就是iterator方法。
terator接口就是対所有的collectson容器迸行元素取出的公共接口。
实现类 | 结构 | 是否为一 | 判断重复 | 如何添加 | 如何删除 | 如何获取 |
ArrayList Vector Stack | 数组 | 否 | 用equals | 数组扩容后放入到数组的最后一个 | 后边元素前移,最后一位为null | 数组下标 |
LinkedList | 链表 | 否 | 新建一个node | 前驱挂后继 | 通过就近原则,从头或尾开始遍历 | |
HashMap | 链表+数组 | key是 value 不是 | 新建一个node(key,v,n),判断:1.key是否存在。2.判断容量是否够,不够自动扩容(数组) | 通过就近原则,从头或尾开始遍历 | ||
TreeSet | 树 | 是 | 和基点进行判断,决定向左还是向右,以次判断如果不存在,存入 | |||
HashSet | 链表+数组 | 是 | 判断内容是否存在,如果不存在,新建一个Node(hash()) |
Collection接口的方法
类型 | 格式 | 作用 |
长度: | public int size() | 返回Collection中的元素数 |
判断: | public boolean isEmpty() | 如果Collection不包含元素,则返回 true。 |
判断: | public boolean contains(Object o) | 如果Collection包含指定的元素,则返回 true。(是由O依次与列表元素进行值比较)(依据的是equals()方法) |
变为数组: | public Object[] toArray() | 返回collection中的所有元素的数组(从第一个元素到最后一个元素) |
变为数组: | public <T> T[] toArray(T[] a) | 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。(从第一个元素到最后一个元素)。 |
添加 | public boolean add(E e) | 向Collection的尾部添加指定的元素(可选操作)。 |
添加 | public boolean addAll(Collection<? extends E> c) | 添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(批量添加) |
添加 | boolean retainAll(Collection<?> c) | 仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。(取交集) |
删除: | void clear() | 从列表中移除所有元素(可选操作) |
删除: | public boolean remove(Object o) | 从此列表中移除第一次出现的指定元素(如果存在)(形参可为值,也可为索引)。(会改变集合的长度) |
删除: | public boolean removeAll(Collection<?> c) | 从列表中移除指定 collection 中包含的其所有元素(可选操作) |
遍历Collection | public Iterator<E> iterator() | 获取 collection 的元素上进行迭代的迭代器。 |
方法:
//通过游标(迭代器)模式 循环集合(简写)(在条件时调用迭代器的next,将返回值付给局部变量x)
for(<X> x:collection) {
System.out.print(x+"\t");
}
原因:iterator()返回在此 collection 的元素上进行迭代的迭代器。
接口 Iterator:(只有三个方法)
boolean hasnext() | |
E next() | |
void remove() |
当在迭代器中使用了两次x.next时,有可能程序有问题。每使用一次就会next一次。(但简写的for循环不会)
List
List接口:其中的元素无序,存入顺序有序,可重复的线性结构,其中存放的是泛型实例的地址不是其值,通过地址访问元素,(在String集合中当原来的String发生改变时,list中的值不发生改变(因为String是常量)因为String的改变是依赖重新创建String对象,返回其地址来实现的,而List中的地址并没有被改变
判断相等的规则:根据两个对象的equals()
将list排序:
Collections.sort(list);// 此方法的形参为List类型
较父接口新增方法:(重点,必须记住)
添加: | public void add(int index, E element) | 在列表的指定位置插入指定元素(可选操作) |
添加: | public boolean addAll(int index, Collection<? extends E> c) | 将指定 collection 中的所有元素都插入到Collection中的指定位置 |
获取 | public E get(int index) | 获得 |
更改 | public E set(int index, E element) | 用指定元素替换列表中指定位置的元素 |
获取索引 | public int indexOf(Object o) | 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 |
*注意:
再用迭代器过程中,不要使用集合操作元素,容易发生异常。
使用迭代器时,不可以在使用迭代器时,使用list实例进行对数据的add操作,这时会引发一个ConcurrentModificationException异常,此异常为当方法检测到对象的并发修改,但不允许这种修改时,抛出的异常。
解决办法:
ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按适当顺序)
(Iterator的子接口 ListIterator可以对列表进行更加多的操作如add,set,remove,还可逆序遍历,boolean hasPrevious(),E previous(),分别对应next和hasnext)
实现类:
1.ArrayList:动态数组
它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。
线性队列式结构,替代了vector(动态数组)(插入,删除较慢,但查询较快)线程不安全的(Arrays类中也有一个ArrayList类,这个 类是一个定长的List,注意区分)(默认生成时长度为10(空参构造))
2.Vector:
线性队列式结构(动态数组),线程安全的,方法基本与ArrayList相同,但各方面的性能都较差。(同步过程慢)
3.LinkedList:LinkedList是一个双向链表,不能随机访问
链表式结构(插入,删除较块,但查询较慢)不同步,get,remove,insert方法在LinkedList的首部或尾部。所有操作在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这样做的好处就是可以通过较低的代价在List中进行插入和删除操作。
构造器:
LinkedList()构造一个空列表。
LinkedList(Collection<? extends E> c)构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。
新增方法:
public void addFirst(E e) 将指定元素插入此列表的开头。
public void addLast(E e) 将指定元素添加到此列表的结尾。
getfirst() 总是获取第一个,和迭代器不同(当列表中没有任何元素时调用会抛出异常)
E peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。1.6加入
getlast
public E removeFirst() 移除并返回此列表的第一个元素。(可以代替迭代器进行操作(只能操作一次))(当列表中没有任何元素时调用会抛出异常)
E pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
public E removeLast() 移除并返回此列表的最后一个元素。
4.Stack:表是后进后出的对象堆栈,线程安全的,继承自Vector。
构造器:
Stack() 创建一个空堆栈。
方法:
public E push(E item) 把项压入堆栈顶部。
public E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。
public E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。
public boolean empty() 测试堆栈是否为空。
set集合
Set(集合):其中的元素有序,存入顺序无序(不保存添加时的顺序),不可重复的集合,不包 含重复元素的 collection
实现类:(全部线程不安全)
1.HashSet:使用哈希算法来存储元素,具有较好的存取,查找特性。
2.TreeSet
3.EnumSet(枚举集)
一:HashSet:重复时不会继续放入,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null元素。
1.不能保证元素的排列顺序(迭代时无序)(存在逻辑顺序)
2.线程不安全
3.可以包含null
存入细节:
当存入时先调用代存元素的hashCode(),用该元素的hashCode值与HashSet中的所以有元素hashCode遍历,遍历到的每个元素的hashCode作比较,如果hashCode不相等,则直接添加;
若hashCode的值一样,则继续用该元素的equals()方法比较(是被添加的equals()方法,与之比较的元素作为参数),如果equals()方法得到的值是一样的,则不添加,如果equals()的值是不一样的,就会将该对象添加。
判断两个元素是否相等的规则:equals相等&&hashCode相等,所以在存入自定义对象时,需要重写方法。
一个重写的示例:
4.类 LinkedHashSet<E>
1>哈希表和链接列表实现。
2>维护着一个运行于所有条目的双重链接列表。
3>此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
二:TreeSet:(自带升序)此实现不是同步的
使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparato 进行排序,具体取决于使用的构造方法(加入时先根据Comparato来比较,是否存在)。
1.当要存入自定义对象时,这个对象需要覆盖Comparable接口的compareTo()方法。(让类具备比较性)
Comparable接口:只要需要进行比较的类都要实现
例如:
2.用比较器来实现比较动作:(让集合具备比较性)
Comparator 可以比较的对象类型(接口,需实现)
在创建treeset时可以传入定向的比较器实例;
TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。
这时再加入对象时就会依据比较器定义的比较方法compare(T o1, T o2)来比较。
存入细节:treeSet调用待存入对象的compareTo()方法与容器中其他的对象一一比较,若不相等则根据红黑树的结构找到它的存储位置,进行存储,若相等则不能存入。
判断是否相等的规则:
int compareTo()(参数为要比较的元素)比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
三:EnumSet(枚举集)
是一个专为枚举类设计的集合类,
在内部以位向量的方式存储,占内存小,运行效率高
不允许插入null
没有构造器,通过类方法创建实例
Queue
用于模拟队列(先进先出)的容器。不允许随机访问
新增方法:
实现类:
1.PriorityQueue(插入时按队列元素的大小进行由小到大排序的队列)
2.Deque接口:双端队列,它的实现类为ArrayDeque(基于数组实现的双端队列)
Map接口
Map<K,V>
键值对模式,将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。当添加重复的key时,新的键值对会覆盖老的键值对
当有映射关系时优先考虑
MAP中不能应用迭代器,当需要获取所有元素时
1.先获取一个视图,再迭代调用获取函数
2.或者:利用Map.Entry
构造器:
HashMap() 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
常用方法:
public V put(K key, V value) 添加 在此映射中关联指定值与指定键。将值放进去,并起个名字,若为重复key时,返回被覆盖的value
public Set<K> keySet() 返回键的 Set 视图。(因为键值唯一所以返回set)
public Collection<V> values() 返回值的 Collection 视图。
public Set<Map.Entry<K,V>> entrySet() 返回键值对 该方法将键和值的映射关系作为对象存储到了set集合中,而这个映射关系的类型就是Map . Entry类型 Map.Entry这个类型具有对键值的set,get方法,是个内部静态类。
public V get(Object key) 获取 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。(可以用来判断此map中是否包含此key值的键值对)
public boolean isEmpty() 判断 如果此映射不包含键-值映射关系,则返回 true。
public boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
public boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
int size() 长度 返回此映射中的键-值映射关系数。
public remove(Object key) 删除 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
public class HashMap<K,V> 基于哈希表的 Map 接口的实现。,如果重复,会用新的覆盖。