集合框架
1
.集合家族体系
Collection是父接口
List和Set是子接口
Map也是一个接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLkYFlgZ-1622787250471)(.\img\集合体系.png)]
2.List接口
2.1 ArrayList
ArrayList
ArrayList 有序的 有下标 线程不安全 允许为null
- 1.初始为一个空的Object数组
- 2.当我们第一次添加元素的时候将 数组的长度赋值为10
3.当集合长度不够用的时候,扩容是原来的1.5倍
4.查询快 添加 删除 慢
package com.qfedu.test1;
import java.util.Date;
/**
* 新闻信息类
* 标题
* 作者
* 日期
* 内容
* @author WHD
*
*/
public class News {
private String title;
private String author;
private Date date;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public News() {
}
public News(String title, String author, Date date, String content) {
this.title = title;
this.author = author;
this.date = date;
this.content = content;
}
@Override
public String toString() {
return "News [title=" + title + ", author=" + author + ", date=" + date + ", content=" + content + "]";
}
}
package com.qfedu.test1;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
/**
* ArrayList 有序的 有下标 线程不安全 允许为null
* 1.初始为一个空的Object数组
* 2.当我们第一次添加元素的时候将 数组的长度赋值为10
* 3.当集合长度不够用的时候,扩容是原来的1.5倍
* 4.查询快 添加 删除 慢
* @author WHD
*
*/
public class TestNews {
public static void main(String[] args) {
// 使用ArrayList集合存放新闻信息
ArrayList<News> list = new ArrayList<News>();
Date date = new Date(2020,8,1);
News n1 = new News("周末竟然和女朋友做这事,全世界都震惊了", "赵四", new Date(), "在家做饭");
News n2 = new News("周末竟然和女朋友做这事,全世界都震惊了", "广坤", new Date(), "在家洗衣服");
News n3 = new News("周末竟然和女朋友做这事,全世界都震惊了", "小宝", date, "在家看电视");
list.add(n1);
list.add(n2);
list.add(n3);
System.out.println("集合原长度" + list.size());
list.remove(0);
list.remove(n2);
System.out.println("删除第二个元素之后集合长度" + list.size());
News n4 = new News("周末竟然和女朋友做这事,全世界都震惊了", "小沈阳", date, "在家跳舞");
News modifyNews = list.set(1, n4);
System.out.println("修改之前的元素内容" + modifyNews);
System.out.println("修改之后的元素内容" + list.get(1));
System.out.println("清空集合之前" + list.isEmpty());
System.out.println("===========================");
// 遍历集合
// for循环
// 第一种方式
for(int i = 0; i < list.size() ; i ++) {
System.out.println(list.get(i));
}
System.out.println("===========================");
// 第二种方式 增强for循环
// 格式 for(Type name : list){
//
// }
for(News ns : list) {
System.out.println(ns);
}
System.out.println("===========================");
// 第三种方式 迭代器的方式
// 迭代器必须使用while循环类遍历 因为 没有下标
Iterator<News> it = list.iterator();
while(it.hasNext()) {
News next = it.next();
System.out.println(next);
}
list.clear();
System.out.println("清空集合之后" + list.isEmpty());
}
}
遍历ArrayList方法
1.普通for循环遍历
2.增强for循环遍历(foreach)
3.迭代器遍历
总结:
三种遍历方式的优缺点:
- 1.for循环是基于下标查找的 所以我们可以做一些基于下标的操作
- 2.如果不需要对下标的操作 推荐使用增强for循环或者迭代器
3.不要在增加for循环或者迭代器中删除或者添加数据 将会报并发访问异常
4.增强for内部依然是迭代实现的,是JDK1.5新添加的内容,迭代器是JDK1.2有的
package com.qfedu.test1;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 三种遍历方式的优缺点:
* 1.for循环是基于下标查找的 所以我们可以做一些基于下标的操作
* 2.如果不需要对下标的操作 推荐使用增强for循环或者迭代器
* 3.不要在增加for循环或者迭代器中删除或者添加数据 将会报并发访问异常
* @author WHD
*
*/
public class TestForeach {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<Integer>();
for (int i = 0; i < 200000; i++) {
list1.add(i);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < list1.size(); i++) {
if(i == 1) {
list1.remove(i);
}
System.out.println(list1.get(i));
}
long endTime = System.currentTimeMillis();
System.out.println("普通循环耗时" + (endTime - startTime)); // 1700 毫秒
startTime = System.currentTimeMillis();
// 增强for循环 是JDK1.5 才有的 内部依然使用迭代器实现
for(Integer i : list1) {
System.out.println(i);
}
endTime = System.currentTimeMillis();
System.out.println("增强循环耗时" + (endTime - startTime)); // 1439毫秒
startTime = System.currentTimeMillis();
// 迭代器 1.2
Iterator<Integer> it = list1.iterator();
while(it.hasNext()) {
list1.remove(it.next());
System.out.println(it.next());
}
endTime = System.currentTimeMillis();
System.out.println("迭代器耗时" + (endTime - startTime)); // 600毫秒
}
}
ArrayList源代码实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8v1VUppY-1622787250473)(.\img\ArrayList无参构造.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VZfAE6Bp-1622787250475)(.\img\初始化数组长度.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N44MQ7a6-1622787250476)(.\img\确保有足够的空间,如果没有就扩容.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rqKqHmnb-1622787250478)(.\img\扩容并且赋值数组.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-czVNA7j8-1622787250478)(.\img\ArrayList删除元素.png)]
总结:ArrayList特点是查询快,添加和删除慢,因为涉及到移动元素,所以我们在一些查询占比高于删除和添加的场景可以使用。比如,电商系统
2.2 Vector
Vector类有和ArrayList相同的API,但是是线程安全的
面试题:
ArrayList和Vector区别?
1.Vector是JDK1.0就有的,ArrayList是JDK1.2才有的
2.Vector无参构造直接给数组长度赋值为10,而ArrayList是第一次添加内容的时候才给数组长度赋值为10
3.Vector扩容是原来的两倍,ArrayList是原来的1.5倍
4.Vector是线程安全的,ArrayList是线程不安全的
遍历方式与ArrayList一致
package com.qfedu.test1;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
public class TestVector {
public static void main(String[] args) {
// 此类与ArrayList有相同的API 先存在的 线程安全的
Vector v1 = new Vector(); // 无参构造直接初始化为10
v1.add(20);
v1.add("赵四");
v1.add(23.0);
// 热插拔
List<Object> v2 = new Vector<Object>();
v2.add(20D);
v2.add(21D);
v2.add(22D);
v2.add(23D);
v2.add(24D);
System.out.println("原集合长度" + v2.size());
System.out.println("删除的元素是" + v2.remove(0));
System.out.println("删除一个元素以后" + v2.size());
System.out.println("第一个元素" + v2.get(0));
v2.set(0, 66D);
System.out.println("第一个元素" + v2.get(0));
System.out.println("清空之前是否为空" + v2.isEmpty());
System.out.println("================================");
for (int i = 0; i < v2.size(); i++) {
System.out.println(v2.get(i));
}
System.out.println("================================");
for (Object object : v2) {
System.out.println(object);
}
System.out.println("================================");
Iterator<Object> it = v2.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
v2.clear();
System.out.println("清空之后是否为空" +v2.isEmpty());
}
}
2.3 LinkedList
特点:
无序的,可以为null,线程不安全的,双向链表
除了提供和ArrayList方法名称相同的方法之外 还提供了链表数据结构特有的一些
单独用于操作 头部 和 尾部的一些方法
添加、删除效率高
查询效率低
使用场景:
仓库管理系统,或者图书管理系统,涉及到频繁的修改数据的
package com.qfedu.test1;
import java.util.LinkedList;
/**
* LinkedList 也是List接口的实现类 也是Deque接口的实现类
* LinkedList既是一个线性表也是一个队列(双向链表)
* 除了提供和ArrayList方法名称相同的方法之外 还提供了链表数据结构特有的一些
* 单独用于操作 头部 和 尾部的一些方法
* @author WHD
*
*/
public class Test1 {
public static void main(String[] args) {
LinkedList list = new LinkedList();
// 无序的 是指空间不连续
list.add("a");
list.add(20);
list.addFirst("B");
list.addLast("C");
list.add(1, "中文");
System.out.println("集合长度" + list.size());
System.out.println("第一个元素是" + list.getFirst());
System.out.println("第二个元素" + list.get(1));
list.getLast();
list.removeFirst();
list.removeLast();
list.remove();
for (Object object : list) {
System.out.print(object + "\t");
}
System.out.println();
System.out.println("删除第一个元素以后,集合长度" + list.size());
list.set(1, "A");
for (Object object : list) {
System.out.print(object + "\t");
}
System.out.println();
System.out.println("集合是否为空" + list.isEmpty());
list.clear();
System.out.println("集合是否为空" + list.isEmpty());
}
}
遍历LinkedList
三种 方式
1.普通for循环
2.增强for循环
3.迭代器
注意:不要使用普通for循环遍历LinkedList
//由于LinkedList是双向链表,因此是算出 i 是在一半前还是一半后,一半前正序遍历、一半后倒序遍历,这就是二分排序。也就是说,LinkedList在get任何一个位置的数据的时候,都会把前面的数据走一遍。假如我有10个数据,那么将要查询1+2+3+4+5+5+4+3+2+1=30次数据,相比ArrayList,却只需要查询10次数据就行了,随着LinkedList的容量越大,差距会越拉越大。
package com.qfedu.test1;
import java.util.Iterator;
import java.util.LinkedList;
public class Test3 {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < 20; i++) {
list.addFirst(i);
}
System.out.println("=================");
// 1 普通for循环
for(int i = 0; i < list.size(); i ++) {
System.out.println(list.get(i));
}
// 2 增强for循环
for(Integer i : list) {
System.out.println(i);
}
// 3 迭代器
Iterator<Integer> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
LinkedList源码解读
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3f6xygqt-1622787250479)(.\img\add方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WMJ5QkdC-1622787250480)(.\img\addFirst方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pwe8MtcR-1622787250481)(.\img\addLast方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U1RAa8VL-1622787250482)(.\img\addLast方法内部实现.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hVTQcOil-1622787250483)(.\img\getFirst方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f6yJbi2b-1622787250484)(.\img\getLast方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJ08Kepc-1622787250485)(.\img\LinkedList查找元素方法.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5A751MNh-1622787250485)(.\img\removeFirst内部实现.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXx78Fia-1622787250486)(.\img\remove方法内部实现.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZVzlIWC-1622787250487)(.\img\每一个元素都是一个Node.png)]
3.Map接口
3.1HashMap
特点:
无序
线程不安全
允许键和值为null 键不能重复
ArrayList是基于数组 有下标 所以查询快 同样也是因为有下标 涉及到移动元素 所以增删慢
LinkedList 基于双向链表 没有下标 所以查询慢 同样也是因为没有下标 增删快
能不能将以上两个集合 结合到一起呢?
可以的 HashMap就是 几乎实现了将两者结合到一起
JDK 1.7 数组 + 单向链表
JDK 1.8 数组 + 单向链表 + 红黑树 当单向的链表的长度大于8时候 转换为红黑树 提高查询效率
扩容 2倍
效率:
增删改查都快只是理想状态,实际中会受到影响,只是会相对提高增删改查的效率,但是缺点是占用空间大
package com.qfedu.test2;
import java.util.ArrayList;
import java.util.HashMap;
public class Test1 {
public static void main(String[] args) {
// 定义一个集合 存储成对的信息
ArrayList<String> list = new ArrayList<String>();
list.add("US美国");
list.add("JP日本");
list.add("CN中国");
HashMap<String,String> map =new HashMap<String,String>();
map.put("US", "美国");
map.put("RU", "俄罗斯");
map.put("CN", "中国");
map.put("JP", "小日本");
System.out.println(map.size());
// map集合 键和值 都允许为 null 键不能重复 如果重复 那么将覆盖值
map.put("JP", "日本");
System.out.println(map.size());
System.out.println(map.get("JP"));
System.out.println("删除的元素value是" + map.remove("JP"));
System.out.println(map.isEmpty());
map.clear();
System.out.println(map.isEmpty());
}
}
遍历方式
1.获取所有key,根据key获取值
2.获取所有的值
3.获取Set<Entry<?,?>> 获取所有的整条数据的集合
4.获取整条数据的集合迭代器map.entrySet().iterator();
package com.qfedu.test2;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
/**
* HashMap 集合特点
* 无序
* 线程不安全
* 允许键和值为null 键不能重复
* 效率
* 增删改查
* ArrayList是基于数组 有下标 所以查询快 同样也是因为有下标 涉及到移动元素 所以增删慢
* LinkedList 基于双向链表 没有下标 所以查询慢 同样也是因为没有下标 增删快
* 能不能将以上两个集合 结合到一起呢?
* 可以的 HashMap就是 几乎实现了将两者结合到一起
* JDK 1.7 数组 + 单向链表
* JDK 1.8 数组 + 单向链表 + 红黑树 当单向的链表的长度大于8时候 转换为红黑树 提高查询效率
* 扩容 2倍
*map== {}时,该值为初始容量(初始容量默认为16);当map被填充
/**负载因子,代表了map的填充度有多少,默认是0.75
加载因子存在的原因,还是因为减缓哈希冲突,如果初始桶为16,等到满16个元素才扩容,某些桶里可能就有不止一个元素了。
所以加载因子默认为0.75,也就是说大小为16的HashMap,到了第13个元素,就会扩容成32。
* @author WHD
*
*/
public class Test2 {
public static void main(String[] args) {
// keySet() 返回所有的key集合 set集合
HashMap<String,String> map =new HashMap<String,String>();
map.put("US", "美国");
map.put("RU", "俄罗斯");
map.put("CN", "中国");
map.put("JP", "小日本");
Set<String> set = map.keySet();
for (String key : set) {
System.out.print(key + "\t" + map.get(key));
System.out.println();
}
System.out.println("=================");
// 获取所有的value values()
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
System.out.println("==================");
Set<Entry<String, String>> entrySet = map.entrySet();
for(Entry en : entrySet) {
System.out.println(en.toString());
}
System.out.println("==================");
// 使用迭代器
Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Entry<String, String> next = iterator.next();
System.out.println(next.getKey() + "===" + next.getValue());
}
}
}
HashMap数据结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qaAj6UFy-1622787250488)(.\img\HashMap.png)]
3.2Hashtable
面试题:
HashMap和Hashtable的区别?
此类提供与Hashtable相同的实现,但是是线程安全的,默认容量是11,扩容是两倍 + 1,键和值都不允许为null,无序的
package com.qfedu.test2;
import java.util.Hashtable;
/**
* Hashtable
* 无序
* 线程安全的
* 键和值都不允许null
* @author WHD
*
*/
public class Test3 {
public static void main(String[] args) {
Hashtable<Integer,String> table = new Hashtable<Integer,String>();
table.put(1, "A");
table.put(2, "B");
table.put(3, "C");
}
}
3.3Properties
Properties:属性
Hashtable子类,也是线程安全的,不要使用put或者putAll方法添加内容,因为此类只用于存放键和值都是String类型
使用 + .setProperty(“CN”, “中国”);添加
package com.qfedu.test1;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
/**
* Properties 类
* Hashtable子类
* 线程安全
* 键和值都为String
* 不要使用put或者putAll方法添加内容
*
* @author WHD
*
*/
public class TestProperties {
public static void main(String[] args) {
// Properties properties1 = System.getProperties();
// properties1.list(System.out);
// properties.put(20, 20.0); // 不要使用put方法来添加内容
//
// properties.get(20);
Properties properties2 = new Properties();
properties2.setProperty("CN", "中国");
properties2.setProperty("US", "美国");
properties2.setProperty("JP", "日本");
properties2.setProperty("KR", "韩国");
properties2.setProperty("RU", "俄罗斯");
properties2.list(System.out);
System.out.println(properties2.size());
System.out.println(properties2.get("CN"));
Set<Entry<Object, Object>> set = properties2.entrySet();
System.out.println("-- listing properties --");
for(Entry<Object, Object> entry : set) {
System.out.println(entry);
}
System.out.println("===============================");
Set<Object> keys = properties2.keySet();
for(Object key : keys) {
System.out.println(properties2.get(key));
}
System.out.println("===============================");
}
}
3.4TreeMap
TreeMap是可以保证顺序的Map集合,要求键必须可以排序,也就是必须实现Comparable接口,重写CompareTo方法
package com.qfedu.test2;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Tree 树
* TreeMap是有顺序的Map集合 所存放的数据Key值必须可以比较 而且是升序的顺序
* 我们自定义的对象必须实现Comparable接口 重写CompareTo方法
* @author WHD
*
*/
public class TestTreeMapAndTreeSet {
public static void main(String[] args) {
TreeMap<String,String> map =new TreeMap<String,String>();
map.put("A","赵四");
map.put("a","广坤");
map.put("h","大拿");
map.put("B","小宝");
map.remove("A");
for(Entry<String,String> entry : map.entrySet()) {
System.out.println(entry);
}
map.clear();
map.size();
map.isEmpty();
System.out.println("=================================");
SortedMap<Person,String> map1 = new TreeMap<Person,String>();
map1.put(new Person("赵四",20), "A");
map1.put(new Person("广坤",21), "F");
map1.put(new Person("小宝",22), "c");
map1.put(new Person("大拿",23), "B");
System.out.println(map1.size());
for(Entry<Person,String> entry : map1.entrySet()) {
System.out.println(entry);
}
System.out.println("=================================");
}
}
package com.qfedu.test2;
/**
* 实现Comparable 自定义比较规则
*/
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Person o) {
if(this.getAge() == o.getAge()) {
return 0;
}else if(this.getAge() > o.getAge()) {
return 1;
}else {
return -1;
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
4.Set接口
4.1 HashSet
HashSet底层是一个HashMap,因为HashMap键不能重复的特点,所以可以使用HashMap维护一个我们创建HashSet
特点:
- 无序
- 不能重复 不允许添加两个对象 A和B A.equals(B) 并且 A和BhashCode相等
线程不安全
可以为null
HashSet去重复是根据对象的hashCode和equals方法比较 都为true 则认为是同一个对象
package com.qfedu.test1;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet
* 无序
* 不能重复 不允许添加两个对象 A和B A.equals(B)
* 线程不安全
* 可以为null
* HashSet去重复是根据对象的hashCode和equals方法比较 都为true 则认为是同一个对象
* @author WHD
*
*/
public class TestHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("A");
set.add("hello");
set.add("20");
set.add("中国");
System.out.println("第二次添加A" + set.add("A"));
System.out.println(set.size());
for(String str : set) {
System.out.println(str);
}
System.out.println("=======================");
Iterator<String> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("=======================");
System.out.println(set.remove("A"));
System.out.println(set.size());
set.clear(); // 清空集合
System.out.println(set.isEmpty());
}
}
4.2LinkedHashSet
HashSet的子类,基于链表的HashSet,可以保证数据的顺序,顺序就是插入的顺序
package com.qfedu.test1;
import java.util.Iterator;
import java.util.LinkedHashSet;
/**
* HashSet是无序的 不能保证顺序
* 如果需要保证顺序 并且元素不能重复 可以使用LinkedHashSet
* LinkedHashSet是基于链表的 HashSet 可以保证元素的顺序 插入顺序
*
* @author WHD
*
*/
public class TestLinkedHashSet {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<String>();
set.add("A");
set.add("hello");
set.add("中国");
set.add("千锋");
set.add("666");
System.out.println("=======================");
for(String str : set) {
System.out.println(str);
}
System.out.println("=======================");
Iterator<String> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("=======================");
set.remove("A");
System.out.println(set.size());
set.clear();
System.out.println("清空集合以后" + set.isEmpty());
}
}
4.3 TreeSet
TreeSet是可以保证顺序的Set集合,与LinkedHashSet不同,TreeSet是-nkedHashSet是按照插入的顺序,TreeSet底层是维护的一个TreeMap,TreeSet要求保存的内容必须可以排序,也就是必须实现Comparable接口,重写CompareTo方法
package com.qfedu.test2;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Tree 树
* TreeMap是有顺序的Map集合 所存放的数据Key值必须可以比较 而且是升序的顺序
* 我们自定义的对象必须实现Comparable接口 重写CompareTo方法
* @author WHD
*
*/
public class TestTreeMapAndTreeSet {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<String>();
set.add("你好");
set.add("A");
set.add("B");
set.add("hello");
for(String str : set) {
System.out.println(str);
}
TreeSet<Worker> set1 = new TreeSet<Worker>();
set1.add(new Worker());
set1.add(new Worker());
set1.add(new Worker());
set1.add(new Worker());
System.out.println(set1.size());
}
}
package com.qfedu.test2;
public class Worker implements Comparable<Worker>{
@Override
public int compareTo(Worker o) {
return 0; // 此处没有定义比较规则 同一返回0 那么将只能添加一个Worker对象 因为所有的Worker对象相比都相等
}
}
5.泛型
泛型
作用:相当于一个 占位 符 可以规范数据类型 有点类似于Object的作用 但是注意不能类型转换
适用场景:
接口,类,抽象类,形参,返回值
泛型可以是任何的字母,一般常用的:
T:Type
E:Element
K:Key
V:Value
package com.qfedu.test2;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 泛型 <T>
* 作用:相当于一个 占位 符 可以规范数据类型 有点类似于Object的作用 但是注意不能类型转换
* 使用场景:
* 接口 类
* 方法形参 返回值
* 占位符 T Type E Element K key V value
* @author WHD
*
*/
public class TestGeneric {
public static void main(String[] args) {
AImpl1 ai = new AImpl1();
ai.m1("hello wolrd");
AImpl2 ai2 = new AImpl2();
ai2.m1(20);
B<String> b = new B<String>();
b.m1();
B<Integer> b1 = new B<Integer>();
b1.m2(1);
E.m1("String");
}
}
class C<K,V>{
public V m1(K k) {
return null;
}
}
class E{
public static <T> void m1(T t) {
System.out.println(t);
}
}
class B<T>{
public T m1() {
return null;
}
public void m2(T t) {
System.out.println(t);
}
}
interface A<T>{
void m1(T sb);
void m2(Object obj);
T m3();
}
class AImpl1 implements A<String>{
@Override
public void m1(String sb) {
}
@Override
public void m2(Object obj) {
}
@Override
public String m3() {
return null;
}
}
class AImpl2 implements A<Integer>{
@Override
public void m1(Integer i) {
System.out.println(i);
}
@Override
public void m2(Object obj) {
}
@Override
public Integer m3() {
return null;
}
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}
class Test{
/**
* ? extends Animal 表示泛型可以是Animal或者Animal的子类
* @param set
*/
public void m1(Set<? extends Animal> set) {
}
public void m2(List<? super Dog> list) {
}
// public void m3(List<Dog extends ?> list) {
//
// }
public static void main(String[] args) {
Test test = new Test();
test.m1(new HashSet<Dog>());
test.m1(new HashSet<Cat>());
test.m1(new HashSet<Animal>());
// test.m1(new HashSet<String>());
test.m2(new ArrayList<Dog>());
test.m2(new ArrayList<Animal>());
// test.m2(new ArrayList<Cat>());
test.m2(new ArrayList<Object>());
}
}
- 111111