Java 集合框架

集合类的由来:
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。

集合特点:

1、用于存储对象的容器。
2、集合的长度是可变的。
3、集合中不可以存储基本数据类型值。

集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。
框架的顶层Collection接口:
Collection的常见方法:

1、添加:

boolean add(Object obj);
boolean addAll(Object obj); //将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

2、删除:
  boolean remove(Object obj);
  boolean removeAll(Collection coll);  //将两个集合中的相同元素从调用removeAll的集合中删除。
  void clear();

3、判断:
  boolean contains(Object obj);
  boolean containsAll(Collection coll); //如果此 collection 包含指定 collection 中的所有元素,则返回 true。
  boolean isEmpty(); //判断集合中是否有元素。

4、获取:
  int size(); //返回此 collection 中的元素数。
  Iterator iterator(); //取出元素的方式,迭代器

该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的。对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可。也就是iterator方法。

5、其他:

  boolean retainAll(Collection coll);  //取交集,保留和指定的集合相同的元素,而删除不同元素。
  Object[] toArray();      //将集合转成数组。

------------------------------------------------------------------------
list和Set的特点:
Collection
  | -- List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
  | -- Set:元素不能重复,无序。


List:特有的常见方法:有一个共性特点就是都可以操作角标。

1、添加:
  void add(index,element);
  void add(index,collection);

2、删除:
  Object remove(index);

3、修改:
  Object set(index,element);

4、获取:
  Object get(index);
  int indexOf(Object);
  int lastIndexOf(Objectj);
  List subList(from,to);


List集合是可以完成对元素的增删改查。
List:
  | -- Vector:内部是数组数据结构,是线程安全的。增、删、查都很慢!效率低
  | -- ArrayList:内部是数组数据结构,是线程不安全的。替代了Vector。查询的速度很快、增删慢。ArrayList是List接口实现类,可以动态调整大小的数组。
不同步,默认初始容量为10,当元素超过10个以后,会重新分配内存空间,并将所有的对象从较小的数组中拷贝到较大数组中,那么容量变化的规则是(旧容量*3)/2+1
  | -- LinkedList:内部链表的数据结构,是线程不安全的。增、删除元素的速度很快,查询很慢效率高。

底层数据结构由链表和哈希表组成。由链表保证元素有序。
由哈希表保证元素唯一。
  LinkedList: 
  addFirst();
  addLast();
  getFirst(); // 获取但不移除,如果链表为空,抛出NoSuchElementException
  getLast();

jdk1.6
  peekFirst(); //获取但不移除,如果链表为空,返回Null
  peekLast();
  removeFirst();
  removeLast();
jdk1.6
  pollFirst(); // 获取但不移除,如果链表为欧诺个,抛出NoSuchElementException
  pollLast(); //获取但不移除,如果链表为空,返回Null

----------------------------------------------------------------------------
Set:元素唯一、是无序。
set接口中的方法和collection一致。
  | -- HashSet:内部数据结构是哈希表,是不同步的。
   哈希表依赖两个方法:hashCode()和equals()
执行顺序:
  首先判断hashCode()值是否相同
  是:继续执行equals(),看其返回值是true:说明元素重复,不添加是false:就直接添加到集合。
  否:就直接添加到集合
  最终:自动生成hashCode()和equals()即可

  | -- TreeSet:可以对Set集合中的元素进行排序。底层数据结构是红黑树。(是一种自平衡的二叉树)
  判断元素的唯一性的方式,就是根据比较方法的返回结果是否是0,是,就是相同元素,不存

TreeSet对象元素进行排序的方式一:
让元素自身具备比较功能,元素就需要实现comparble接口。覆盖compareTo方法。如果不要按照对象中具备的自然顺序进行排序,如果对象中不具备自然顺排序,怎么办?

可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
 
哈希值确定元素是否相同:
1、判断是否两个元素的哈希值是否相同。
  如果相同,再判断两个对象的是否内容相同。

2、判断哈希值相同,其实判断的是对象的hashCode的方法。and内容相同,用的是euals方法。
  注意:如果哈希值不同,是不需要判断equals。
  HashSet集合数据结构是哈希表 ,所以存储元素的时候,使用的元素hashCode方法来确定位置,如果位置相同,在通过元素来确定是否相同。 

---------------------------------------------------------------------------------------
Map :
  一次添加一对元素。Map的每一个元素由两部分组成,分别是 key(键)和  value(值)Collection 一次添加一个元素。
  Map 也称为双列集合,Collection集合称为单列集合。其实map集合中存储的就是键值对。Map集合中必须保证键的唯一性。 

Map底层实现是数组和链表
常用方法:

1、添加:
  value put(key,value); //返回前一个和key关联的值,如果没有则返回null。

2、删除:
  void clear(); //清空map集合。

3、判断:
  boolean containsKey(Object key) ; //如果此映射包含指定键的映射,则返回 true 。 
  boolean containsValue(Object value) ; //如果此地图将一个或多个键映射到指定的值,则返回 true 。 
  boolean isEmpty() ; //如果此地图不包含键值映射,则返回 true 。 

4、获取:
  value get(key); //返回到指定键所映射的值,或 null如果此映射包含该键的映射。 
  int size(); //获取键值对的个数。
Map常用子类
  | -- HashTable :内部结构是哈希表,是线程同步的,效率低。不允许null值(key和value都不允许null)。
  哈希表依赖两个方法:hashCode()和equals()

执行顺序:
  首先判断hashCode()值是否相同
  是:继续执行equals(),看其返回值是true:说明元素重复,不添加是false:就直接添加到集合。
  否:就直接添加到集合。
  最终:自动生成hashCode()和equals()即可。

  | -- Properties: 用来存储键值对型的配置文件的信息,可以和IO技术相结合。
  | -- HashMap :内部结构是哈希表,不是同步的。允许null值(key和value都允许null)。HashMap扩容标准16 * 0.75 =12,
HashMap非线程安全扩容必须满足两个条件:
  1、存放新值的时候当前已有元素的个数必须大于等于阈值。
  2、存放新值的时候当前存放数据发送hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)。

ArrayList,Vector,LinkedList的存储性能和特性HashMap和Hashtable的区别       
ArrayList实现了长度可变的数组,在内存分配连续的空间,遍历元素和随机 访问元素的效率比较高。 
Vector:以数组的方式存储,增、删慢,查、改快。       
ArrayList:线程不安全,速度快  (默认初始容量为10)   
Vector:线程安全,速度慢(synchronized)。       
LikedList:以单链表的方式存储,增,删快,查,改慢

HashMap和HashTable之间的区别:        
  这两个都是Map接口的实现类,实现了将唯一键映射到特定的值上。
  HashMap类没有排序,可以有一个null键和多个null值,HashTable不可以有null键和null值。       
  HashTable:线程安全,线程安全就是防止覆盖更新。       
  HashMap:非线程安全(默认初始容量16)

哈希表依赖两个方法:hashCode()和equals()
执行顺序:
  首先判断hashCode()值是否相同
  是:继续执行equals(),看其返回值是true:说明元素重复,不添加是false:就直接添加到集合
  否:就直接添加到集合
  最终:
  自动生成hashCode()和equals()即可

  | -- TreeMap :内部结构是二叉树,不是同步的 。可以对Map集合中的键进行排序。
  如何保证元素唯一性呢?根据比较的返回值是否是0来决定
  如何保证元素的排序呢?
两种方式
              自然排序(元素具备比较性) 让元素所属的类实现Comparable接口
              比较器排序(集合具备比较性)让集合接收一个Comparator的实现类对象

  | -- LinkedHashMap:底层数据结构由链表和哈希表组成。
  由链表保证元素有序。
  由哈希表保证元素唯一。

----------------------------------------------------------------------------------

泛型:
jdk1.5出现了安全机制
好处:
  1、将运行时期的问题ClassCastException转到了编译时期。
  2、避免了强制转换的麻烦。
  < >:什么时候用?当操作的引用数据类型不确定的时候。 就使用< >。将要操作的引用数据类型传入即可。其实< >就是一个用于接收具体引用数据类型的参数范围。
在程序中只要用到带有< >的类或者接口,就要明确传入的具体引用数据类型泛型技术是给编译器使用的技术,用于编辑时期,确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。为什么擦除?因为是为了兼容运行的类加载器。

泛型补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者再强制转换了。当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型只
能将泛型定义在方法上。

原文地址:https://www.cnblogs.com/lwx57280/p/12489369.html