泛型
参数化类型(泛指某个类型)就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定 义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型类:
定义一个泛型类:
public class ClassName<T>{
private T data; public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型接口
public interface IntercaceName{
T getData();
}
泛型方法
private static T 方法名(T a, T b) {}
public static <A> void print(A a){}
泛型限制类型:
在使用泛型时, 可以指定泛型的限定区域 ,
例如: 必须是某某类的子类或 某某接口的实现类,格式:
<T extends 类或接口1 & 接口2>
泛型中的通配符 ?
类型通配符是使用?代替方法具体的类型实参。
1 指定了泛型类型的上届
2 指定了泛型类型的下届
3 指定了没有限制的泛型类型
Plate<? extend Fruit> p = new Plate<Apple>();
Plate<? super Applex> p = new Plate<Apple>();
interface Fruit{}
class Apple implements Fruit{}
class Plate<T>{
T data;
}
作用
1、 提高代码复用率
2、 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
注意
在编译之后程序会采取去泛型化的措施。 也就是说Java中的泛型,只在编译阶段有效。
在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加
类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
类集
Java对数据额结构成熟的实现
三个接口Collection;Map;Iterator
Collection
存储单个数据的顶级接口
Map
存储双值的最大接口
迭代器:
Iterator:
迭代Collection下所有集合
对所有集合进行迭代的实现,对每一个类集里的数据结构,数据结果最优的获取方式
ListIterator:
迭代List下集合
链表
linked list,由一系列结点node(链表中每一个元素称为结点)组成
class Node{
Object data;
Node next;
}
二叉树
binary tree ,是每个结点不超过2的有序树(tree) 。
class Node{
Object data;
Node left;
Node right;
}
Collection
Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。
方法:
1 public boolean add(E e) 普通 向集合中插入一个元素
2 public boolean addAll(Collection c) 普通 向集合中插入一组元素
3 public void clear() 普通 清空集合中的元素
4 public boolean contains(Object o) 普通 查找一个元素是否存在
5 public boolean containsAll(Collection c) 普通 查找一组元素是否存在
6 public boolean isEmpty() 普通 判断集合是否为空
7 public Iterator iterator() 普通 为 Iterator 接口实例化
8 public boolean remove(Object o) 普通 从集合中删除一个对象
9 boolean removeAll(Collection c) 普通 从集合中删除一组对象
10 boolean retainAll(Collection c) 普通 判断是否没有指定的集合
11 public int size() 普通 求出集合中元素的个数
12 public Object[] toArray() 普通 以对象数组的形式返回集合中的全部内容
13 T[] toArray(T[] a) 普通 指定操作的泛型类型,并把内容返回
14 public boolean equals(Object o) 普通 从 Object 类中覆写而来
15 public int hashCode() 普通 从 Object 类中覆写而来
ps:在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。
List 接口
在整个集合中 List 是 Collection 的子接口,里面的所有内容都是允许重复的。
方法:
1 public void add(int index,E element) 普通 在指定位置处增加元素
2 boolean addAll(int index,Collection c) 普通 在指定位置处增加一组元素
3 public E get(int index) 普通 根据索引位置取出每一个元素
4 public int indexOf(Object o) 普通 根据对象查找指定的位置,找不到返回-1
5 public int lastIndexOf(Object o) 普通 从后面向前查找位置,找不到返回-1
6 public ListIterator listIterator() 普通 返回 ListIterator 接口的实例
7 public ListIterator listIterator(int index) 普通 返回从指定位置的 ListIterator 接口的实例
8 public E remove(int index) 普通 删除指定位置的内容
9 public E set(int index,E element) 普通 修改指定位置的内容
10 List subList(int fromIndex,int toIndex) 普通 返回子集合
常用的实现类有如下几个: · ArrayList(95%)、Vector(4%)、LinkedList(1%)
ArrayList:使用的是数组结构,对于增加删除慢,查找快。
向右移>>
Vector:与 ArrayList 一样,Vector 本身也属于 List 接口的子类,此类的定义如下:
LinkedList:使用双向链表结构,增加删除快查找慢
set接口:
不包含重复元素的集合。 更正式地说,集合不包含元素对 e1 和 e2 ,使得 e1.equals(e2) 和最多一个null元素。 正如其名称所暗示的,此接口模拟数学集抽象。
Set 接口也是 Collection 的子接口,与 List 接口最大的不同在于,Set 接口里面的内容是不允许重复的。
注意:如果将可变对象用作set元素,则必须非常小心。
两种获取方式:
1、toArray()
2、iterator()
HashSet:
散列存放数据结构。(哈希表)内部有HashMap(双值存储)的对象,使用HashMap进行存储。
TreeSet
采用有序的二叉树进行存储,基于TreeMap
此类的iterator方法返回的迭代器是快速失败的 ,出现异常
Comparable接口:
this 与 o 比较,返回的数据:负数 this 小 /0一样大/正数 this 大
Map
Map集合存储的是一个个的 键值对(钥匙和锁 ) 数据,Map集合键(key)不可重复。
将键映射到值的对象。 映射不能包含重复的键; 每个键最多可以映射一个值。不要乱改已在Map集合中存储的键的对象。
方法:
get(Object key):返回指定键映射到的值,如果此映射不包含键的映射,则返回null 。
keySet():
put(K key, V value):将指定的值与此映射中的指定键相关联(可选操作)。 如果映射先前包含键的映射,则旧值将替换为指定的值。返回与key关联的先前值,如果null没有关联。
remove(Object key):如果存在,则从该映射中移除键的映射(可选操作)。
HashMap:
基于哈希表的Map接口的实现。
HashMap
的实例有两个影响其性能的参数: 初始容量和散列因子 。当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即,重建内部数据结构),以便哈希表具有大约两倍的桶数。
Objiect.hashCode:初始桶数量 16,散列因子 0.75(当占比超75%扩容)哈希桶中数据量大于8时,从链表转为红黑二叉树。当哈希桶中的数据量减少到6时,从红黑二叉树转换为链表。
容器
HashMap:线程不安全,效率低
Hashtable:线程安全,效率低
concurrentHashMap:采用分段锁机制,保证线程安全效率又比较高
forEach:
增强for循环,最早出现在C#中。用于迭代数组或集合(Collection)。
语法:
for(数据类型 变量名:集合或数组名){}