泛型
概念
泛型概念非常重要,它是程序的增强器,它是目前主流的开发方式。
泛型是(Generics)是JDK1.5 的一个新特性,其实就是一个『语法糖』,本质上就是编译器为了提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓『泛型』的概念的。
作用
通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期
代码通用性更强
泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的。
泛型的<>里只能写引用类型。
泛型声明
泛型可以在接口、方法、返回值上使用:
java.util.List泛型接口/类:
public interface Collection
泛型方法的声明:
public
在方法返回值前声明了一个
常用名称
l E - Element (在集合中使用,因为集合中存放的是元素)
l T - Type(Java 类)
l K - Key(键)
l V - Value(值)
l N - Number(数值类型)
l ? - 表示不确定的java类型
集合
Collection接口
概述
英文名称Collection,是用来存放对象的数据结构,这些对象也称为collection的元素。一些collection允许有重复的元素,而另一些则不允许。一些collection是有序的,而另一些则是无序的。JDK不提供此接口的任何直接实现:它提供更具体的子接口(如Set和List)实现。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。
数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。
集合的继承结构
Collection接口
-- List接口 : 数据有序,可以重复。
-- ArrayList子类
-- LinkedList子类
-- Set接口 : 数据无序,不可以存重复值
-- HashSet子类
Collection接口的共性方法
2.2 List接口
概述
有序的 collection(也称为_序列_)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
特点
1、 数据有序
2、 允许存放重复元素
3、 元素都有索引
4、 允许存放多个 null 元素
常用方法
listIterator()和iterator()的区别:
listIterator()来自List子接口特有的遍历方法,iterator()是来自父接口collection的遍历方法;返回值也是父子关系。
listIterator子接口中还扩展了逆向遍历的方法hasPrevious()
ArrayList
概述
1) 存在于java.util包中。
2) 内部用数组存放数据,封装了数组的操作,每个对象都有下标。
3) 调用add()时,才开始自动扩容,内部数组默认初始容量是10。如果不够会以1.5倍容量增长。
4) 查询快,增删数据效率会降低。
5) JDK1.6里,一旦创建数组对象,就会自动分配10个容量。JDK1.8里,如果不向集合中存放数据,默认是空数组。
6) ArrayList本质上是List接口的实现类,是维护了可变长的一个Object[],可以存放各种元素。
7)创建对象ArrayList()
LinkedList
概述
是List接口的实现类,拥有List接口的所有特点。双向链表,两端效率高。底层是链表,对于链表上的节点,有两个特殊位置是开头及结尾的元素的位置,因为不像数组一样,不是连续空间所以不适合查询,方便增删业务。由Node节点组成。
E element()
获取但不移除此列表的头(第一个元素)。
boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。
E peek()
获取但不移除此列表的头(第一个元素)。
E poll()
获取并移除此列表的头(第一个元素)
E pop()
从此列表所表示的堆栈处弹出一个元素。
void push(E e)
将元素推入此列表所表示的堆栈。
Set接口
概述
Set接口也是Collection接口的子接口,能用父接口的所有方法。
一个不包含重复元素的 collection。
数据无序(因为set集合没有下标)。
由于集合中的元素不可以重复。常用于给数据去重。
最多包含一个 null 元素。
特点
HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
TreeSet:底层就是TreeMap,也是红黑树的形式,便于查找数据。
HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据。
HashSet
概述
此类实现Set接口,拥有set接口的所有特点和方法们,由哈希表/散列表(实际上是一个HashMap实例)支持。它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
创建对象
HashSet()
HashSet底层是HashMap,其底层 HashMap实例的默认初始容量是 16,加载因子是 0.75。,每次往HashSet里存入值时,其实是作为Key存入HashMap中,这时HashMap中,value值为了什么都能存是new了一个Object。而Map中Key是不能重复的,所以Set里也不能存入重复的值;Map是无序的,所以Set也是无序的。
Map接口
概述
java.util接口 Map
类型参数: K - 此映射所维护的键的类型V - 映射值的类型。
也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复.
特点
可以根据键 提取对应的值
键不允许重复,如果重复值会被覆盖
存放的都是无序数据
初始容量是16,默认的加载因子是0.75
原理:
HashMap中存放数据时,拿着你的数据,开始计算存储位置(拿着key哈希算法)。
存储步骤:
1.这个位置是空的,没存过数据,把数据直接存入数组。
2.这个位置存过了,有数据了,就会发生哈希碰撞/哈希冲突,那么就会形成链表的结构(把新的数据挂载在老数据的下面),链表的结构越长,查询就越慢。JDK1.8里对链表的查询进行了优化,当链表的长度>8时,转成红黑树,当红黑树的长度<6时,再转回成链表。
3.影响HashMap性能的两个因素:初始容量和加载因子。
初始容量:是指哈希表中桶的数量,也就是数组(以前是Entry数组,现在是Node数组)的容量,初始容量是16
加载因子:是指哈希表在其容量自动增加之前可以达到多满的一种尺度,默认是0.75;当容量超出阈值(16*0.75)后,会发生rehash的现象(即重建内部数据结构),会自动扩容,大概是原来容量的两倍。我们应该尽量避免rehash的现象,因为需要底层再次开辟空间,初始化,赋值,复制等动作。默认加载因子 (0.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本。
LinkedHashMap优势是可以指定key的顺序
Collections工具类
是专门用来给集合服务的,但是不包含Map