一.泛型Generics
1.自定义泛型
泛型作用
可以帮助我们建立类型安全的容器(集合)。
泛型的本质
就是“数据类型的参数化”。即告诉编译器,在调用泛型时必须传入实际类型,当作参数理解,
常用T、E、V表示。
package 容器练习;
public class TestGenerics {
public static void main(String[] args) {
MyCollection<String> mc=new MyCollection<>(); //相当于实参
mc.set("dj",0);
//mc.set(8888,1);
String str=mc.get(0);
// Integer a=(Integer)mc.get(1);
System.out.println(str);
}
}
class MyCollection<E>{ //这里E相当于形参
Object[] objs=new Object[5];
public void set(E e,int index) {
objs[index]=e;
}
public E get(int index) {//返回索引位置的内容
return (E)objs[index];
}
}
2.容器中使用泛型
Collection、List、Set、Map、Iterator接口都定义了泛型
因此,我们在使用这些接口及其实现类时,都要使用泛型。
二.Collection接口
Collection 表示一组对象,它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。
1.Collection接口中定义的方法(List、Set接口中同样适用)
方法 | 说明 |
---|---|
boolean add(Object element) | 增加元素到容器中 |
boolean remove(Object element) | 从容器中移除元素 |
boolean contain(Object element) | 容器中是否包含该元素 |
int size() | 容器中元素的数量 |
boolean inEmpty() | 容器是否为空 |
void clear() | 清空容器中所有元素 |
Iterator iterator() | 获得迭代器,用于遍历所有元素 |
两个容器(集合)的操作
方法 | 说明 |
---|---|
boolean containsAll(Collection c) | 本容器是否包含c容器的所有元素 |
boolean addAll(Collection c) | 将容器c中所有元素增加到本容器 |
boolean removaAll(Collection c) | 移除本容器和容器c中都包含的元素 |
boolean retainAll(Collection c) | 取本容器和容器c中都包含的元素,移除非交集元素(取交集) |
Object[] toArray() | 转化成Object数组 |
常用方法代码
public class TestList {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
System.out.println("容器c的大小:" + c.size());
System.out.println("容器c是否为空:" + c.isEmpty());
c.add("dj01");
c.add("dj02");
System.out.println(c); // 打印时默认调用toString方法
System.out.println("是否包含dj01:" + c.contains("dj01"));
boolean b = c.remove("dj00");
System.out.println("移除dj00:" + b);
c.remove("dj01"); // 从容器中移除,对象还存在,只是把容器中指向对象的地址删除了
System.out.println("移除后:" + c);
Object[] objs = c.toArray();
System.out.println(objs);
c.clear();
System.out.println(c.size());
}
}
两个容器的操作,方法代码
public static void test02() {
List<String> list01=new ArrayList<String>();
list01.add("1");
list01.add("2");
list01.add("3");
List<String> list02=new ArrayList<String>();
list02.add("1");
list02.add("4");
list02.add("5");
System.out.println("list01:"+list01);
// list01.addAll(list02); //list02全部放到list01中
// System.out.println("list01:"+list01);
// list01.removeAll(list02); //list01去掉list02存在的
// System.out.println("list01:"+list01);
// list01.retainAll(list02); //取交集
// System.out.println("list01:"+list01);
System.out.println(list01.containsAll(list02));
}
三.List接口
1.List特点和常用方法
List是有序、可重复的容器。
有序:List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。
可重复:List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。
List接口常用的实现类有3个
ArrayList、LinkedList和Vector
List接口定义的方法
方法 | 说明 |
---|---|
void add(int index,Object element) | 在指定位置插入元素,以前元素全部后移一位 |
Object remove(int index) | 删除指定位置的元素,后面元素全部前移一位 |
Object set(int index,Object element) | 修改指定位置的的元素 |
Object get(int index) | 返回指定位置的元素 |
int indexOf(Object o) | 返回第一个匹配元素的索引,如果没有该元素,返回-1 |
int lastIndexOf | 返回最后一个匹配元素的索引,如果没有该元素,返回-1 |
List接口方法代码
public static void test03() {
List<String> list=new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
System.out.println(list);
list.add(2, "dj");//索引位置插入元素
System.out.println(list);
list.remove(1);//删除索引位置
System.out.println(list);
list.set(2, "dj02");//设置索引位置处的值
System.out.println(list);
System.out.println(list.get(3));//返回索引位置处的值
System.out.println(list.indexOf("A"));//返回元素第一次出现的索引位置
System.out.println(list.lastIndexOf("A"));//返回元素最后一次出现的索引位置
}
2.ArrayList特点和底层实现
ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。我们一般使用它。
ArrayList底层使用Object数组来存储元素数据。所有的方法,都围绕这个核心的Object数组来开展。
3.LinkedList特点和底层实现
LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。 所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。
4.Vector向量
Vector底层是用数组实现的List,相关的方法都加了同步检查,因此“线程安全,效率低”。
5.List接口常用的实现类的选取
如何选用ArrayList、LinkedList、Vector?
1. 需要线程安全时,用Vector。
2. 不存在线程安全问题时,并且查找较多用ArrayList(一般使用它)。
3. 不存在线程安全问题时,增加或删除元素较多用LinkedList。
四、Set接口
1.Set特点
Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。
Set接口常用的实现类
HashSet、TreeSet
2.HashSet
用法和Collection接口中定义的方法一样
HashSet是采用哈希算法实现,底层实际是用HashMap实现的。
实现Comparable接口。
3.TreeMap
TreeSet底层实际是用TreeMap实现的,内部维持了一个简化版的TreeMap,通过key来存储Set的元素。 TreeSet内部需要对存储的元素进行排序,因此,我们对应的类需要实现Comparable接口。这样,才能根据compareTo()方法比较对象之间的大小,才能进行内部排序。
五.Map接口
Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。
Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。
键-值对象是任意的。
Map接口中常用的方法
方法 | 说明 |
---|---|
Object put(Object key,Object value) | 存放键值对 |
Object get(Object key) | 通过键对象查找得到值对象 |
Object remove(Object key) | 删除键对象对应的键值对 |
boolean containsKey(Object key) | Map容器中是否包含键对象对应的键值对 |
boolean containsValue(Object Value) | Map容器中是否包含值对象对应的键值对 |
int size() | 包含键值对的数量 |
boolean isEmpty() | Map是否为空 |
void putAll(Map t) | 将t的所有键值对存放到本map对象中 |
void clear() | 清空本map对象所有键值对 |
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> m1=new HashMap<>();//键和值对象的类型是任意的
m1.put(1, "one");
m1.put(2, "two");
m1.put(3, "three");
System.out.println(m1);
System.out.println(m1.size());
System.out.println(m1.isEmpty());
System.out.println(m1.containsKey(2));
System.out.println(m1.containsValue("three"));
Map<Integer, String> m2=new HashMap<>();
m2.put(4,"四");
m2.put(5,"五");
m1.putAll(m2);
System.out.println(m1);
//map中键不能重复,如果重复(是否重复根据equals方法来判断),则新的覆盖旧的
}
}
public class TestMap2 {
public static void main(String[] args) {
Employee e1=new Employee(1001, "dj", 50000);
Employee e2=new Employee(1002, "二二", 4000);
Employee e3=new Employee(1003, "三三", 3000);
Map<Integer, Employee> map =new HashMap<>();
map.put(1001,e1);
map.put(1002,e2);
map.put(1003,e3);
Employee emp=map.get(1002);
System.out.println(emp.getEname());
}
}
//雇员信息
class Employee{
private int id;
private String ename;
private double salary;
public Employee(int id, String ename, double salary) {
super();
this.id = id;
this.ename = ename;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
1.HashMap和HashTable类
HashMap采用哈希算法实现,是Map接口最常用的实现类。 底层采用了哈希表存储数据,键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap在查找、删除、修改方面都有非常高的效率。
HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。
HashMap与HashTable的区别
1.HashMap: 线程不安全,效率高。允许key或value为null。
2.HashTable: 线程安全,效率低。不允许key或value为null。
2.TreeMap(了解)
TreeMap是红黑二叉树的典型实现。