Java集合
1.java集合框架概述
一方面,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。
另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引
用放入容器中。
数组在内存存储方面的特点:
- 数组初始化以后,长度就确定了。
- 数组声明的类型,就决定了进行元素初始化时的类型
数组在存储数据方面的弊端:
- 数组初始化以后,长度就不可变了,不便于扩展 .
- 数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。同时无法直接获取存储元素的个数 .
- 数组存储的数据是有序的、可以重复的。存储数据的特点单一 .
– Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组.
Java 集合可分为 Collection 和 Map 两种体系
-
Collection接口:单列数据,定义了存取一组对象的方法的集合
1.List:元素有序、可重复的集合
2.Set:元素无序、不可重复的集合
-
– Map接口:双列数据,保存具有映射关系“key-value对”的集合
2.Collection接口的方法
2.1Collection 接口
Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也
可用于操作 List 和 Queue 集合。
JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从
JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型。
2.2Collection接口方法
- 添加
add(Object obj)
addAll(Collection coll)
Collection<String> c = new ArrayList<>();//<>尖括号这是jdk1.5后版本才有的新特性,泛型,指定传入的类型。
c.add("张三");
System.out.println(c);
//add(int index,Object o):在指定的位置添加元素
((ArrayList) c).add(1,18);
Collection c1 = new ArrayList();
c1.add("李四");
c1.add("王五");
System.out.println(c1);
c.addAll(c1);
System.out.println(c);
-
获取有效元素的个数
int size()
System.out.println(c.size());
-
清空集合
void clear()
c.clear();//清空集合的方法
System.out.println(c);
- 是否是空集合
boolean isEmpty()
//isEmpty() :判断集合是否为空,如果为空则返回true,不为空则返回false
System.out.println("集合是否为空:"+c.isEmpty());
- 是否包含某个元素
boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
//contains(Object o) :判断集合中是否包含指定的元素。返回值是boolean类型
System.out.println("是否有张三存在:"+c.contains("张三"));
boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。
- 删除
boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
//remove()方法:删除某个元素
c.remove(18);
boolean removeAll(Collection coll):取当前集合的差集
- 取两个集合的交集
boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
- 集合是否相等
boolean equals(Object obj)
- 转成对象数组
Object[] toArray()
10.获取集合对象的哈希值
hashCode()
11.遍历
iterator():返回迭代器对象,用于集合遍历 .
3.Iterator迭代器接口
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该
对象的内部细节。迭代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空
姐”。
Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection
接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必
须有一个被迭代的集合。
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前.
代码示例:
/*** 迭代器 */
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("张无忌");
c.add("赵敏");
c.add("小昭");
c.add("周芷若");
//使用迭代器遍历集合 获取迭代器对象
Iterator it = c.iterator();
//hasNext():判断集合中是否有下一个元素存在。如果有则返回true,没有则返回false
while (it.hasNext()){
//next():获取集合中的下一个元素
System.out.println(it.next());
}
System.out.println("=================");
//使用foreach遍历集合
for (Object o : c)
{
System.out.println(o);
}
}
}
4.Collection子接口之一List:
4.1List接口的描述
List的特点:
(1)有序
(2)可重复
(3)有索引
鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。
4.2List实现类之一:ArrayList
ArrayList底层是基于数组的(Object o[])
ArrayList 是 List 接口的典型实现类、主要实现类
本质上,ArrayList是对象引用的一个”变长”数组
ArrayList的JDK1.8之前与之后的实现区别?
JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量
为10的数组.
ArrayList代码示例:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*ArrayList类 */
public class ArrayListDemo {
public static void main(String[] args) {
//创建ArrayList对象
List list = new ArrayList();
//添加元素
list.add(1);
list.add(2);
list.add(4);
list.add(5);
list.add(3);
list.add(3);
//遍历集合 List集合是有序的,可重复的,有索引的
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}//get():通过索引获取元素
System.out.println("索引号为0的元素是:"+list.get(0));
//set(int index,Object o)修改元素
list.set(5,6);
//使用toString转换为字符后输出
System.out.println(list.toString()); //删除元素:可以通过指定索引的方式删除元素
list.remove(1); System.out.println(list.toString());
//判断集合是否为空
System.out.println("集合是否为空:"+list.isEmpty());
}
}
ArrayList的扩容机制(非常重要,面试题容易被问)。
在jdk8之前默认长度为10,当超过默认长度时开始扩容,扩容为原来的大约1.5倍
在jdk8中,默认长度为空,当添加第一个元素时,长度会扩容为10,当超过10,那么进行扩容,扩容为
原来的大约1.5倍
4.3List实现类之二:LinkedList
对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
新增方法:
void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()
==LinkedList:==双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。
同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个
变量:
prev变量记录前一个元素的位置
next变量记录下一个元素的位
4.4List实现类之三:Vector
Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程
安全的。
在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比
ArrayList慢,所以尽量避免使用。
新增方法:
void addElement(Object obj)
void insertElementAt(Object obj,int index)
void setElementAt(Object obj,int index)
void removeElement(Object obj)
void removeAllElements()
4.5ArrayList和LinkedList的异同(面试题非常重要)
二者都线程不安全,相对线程安全的Vector,执行效率高。此外,ArrayList是实现了基于动态数组的数
据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因
为LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因
为ArrayList要移动数据。
4.6ArrayList和Vector的区别(面试题非常重要 )
(1)Vector是线程安全的,ArrayList是线程不安全。
(2)因为ArrayList线程不安全,所以性能会更好一下。
(3)Vector如果要扩容,则扩容为原来的2倍,而ArrayList扩容,如果是JDK1.7(包括)之前,初始化
容量为10,如果要扩容,扩容为原来的大约1.5倍。如果是JDK1.7(不包括)之后,默认初始容量为
空,当添加第一个元素时,容量变为10,当超过10以后进行扩容,扩容为原来的大约1.5倍。
5.Collection子接口之二Set:
Set 接口概述
- Set接口是Collection的子接口,set接口没有提供额外的方法。
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
- Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法。
5.1Set实现类之一:HashSet
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
– HashSet 具有以下特点:
不能保证元素的排列顺序
HashSet 不是线程安全的
集合元素可以是 null
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的
equals() 方法返回值也相等。
对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相
等规则。即:“相等的对象必须具有相等的散列码”。
其实HashSet底层是基于HashMap的
/*** Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */
public HashSet() {
map = new HashMap<>();
}
HashSet代码示例:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
//创建HashSet集合的对象
HashSet set = new HashSet();
//添加元素
set.add("一");
set.add("三");
set.add("二");
set.add("四");
set.add("四");
//删除元素
set.remove("一");
//判断是否为空
System.out.println("集合是否为空?"+set.isEmpty());
//HashSet的特点:无序的、不可重复的
Iterator it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
如果集合中添加的是对象,那么需要使用hashcode与equals进行比较:
package collection;
import java.util.HashSet;
import java.util.Objects;
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
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;
}
//重写equals方法和HashCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override//重写toString方法
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class PersonHashCodeDemo {
public static void main(String[] args) {
HashSet set = new HashSet();
Person p1 = new Person("张三",18);
Person p2 = new Person("李四",19);
Person p3 = new Person("王五",18);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set.toString());
}
}
向HashSet中添加元素的过程:
当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的
hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象在 HashSet 底层数组中的存储
位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可
能保证能均匀存储元素,越是散列分布,该散列函数设计的越好)
如果两个元素的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失
败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链
接。
如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存
储在不同的位置,但依然可以添加成功。
HashCode与equals的区别(面试题)
二者都会是用来做比较的,Hashcode相同的对象,他们的equals不一定相同,而equals相同的对象,
他们的Hashcode值一定相同。一般比较会先去比较HashCode值,如果不相同,则两个对象一定不相
同,如果HashCode相同,则再去比较equals。如果equals也相同,则两个对象相同,否则就不相同。
5.2Set实现类之二:LinkedHashSet
LinkedHashSet 是 HashSet 的子类
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的
次序,这使得元素看起来是以插入顺序保存的。
LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
LinkedHashSet 不允许集合元素重复。
5.3Set实现类之二:TreeHashSet
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet底层使用红黑树结构存储数据
新增的方法如下: (了解)
Comparator comparator()
Object first()
Object last()
Object lower(Object e)
Object higher(Object e)
SortedSet subSet(fromElement, toElement)
SortedSet headSet(toElement)
SortedSet tailSet(fromElement)
TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
TreeSet和后面要讲的TreeMap采用红黑树的存储结构
特点:有序,查询速度比List快
6.Map接口
-
Map与Collection并列存在。用于保存具有映射关系的数据:key-value.
-
Map 中的 key 和 value 都可以是任何引用类型的数据.
-
Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals() 方法 .
常用String类作为Map的“键”
-
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value .
-
Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类.
package collection;
import java.util.*;
public class MapDemo01 {
public static void main(String[] args) {
Map map = new HashMap();
//添加、删除、修改操作:
// Object put(Object key,Object value):
// 将指定key-value添加到(或修改)当前map对象中
map.put(1,"AA");
map.put(2,"AA");
map.put(3,"AA");
map.put(4,"AA");
map.put(5,"AA");
System.out.println(map);
// void putAll(Map m):将m中的所有key-value对存放到当前map中
Map map1 = new HashMap();
map1.put(6,"eqe");
map1.put(7,"dad");
map.putAll(map1);
//System.out.println(map);
// Object remove(Object key):移除指定key的key-value对,并返回value
// void clear():清空当前map中的所有数据 – 元素查询的操作:
// Object get(Object key):获取指定key对应的value
// boolean containsKey(Object key):是否包含指定的key
// System.out.println(map.containsKey(8));//false
// boolean containsValue(Object value):是否包含指定的value
//System.out.println(map.containsValue("AA"));
// int size():返回map中key-value对的个数
// System.out.println(map.size());
// boolean isEmpty():判断当前map是否为空
//System.out.println(map.isEmpty());
// boolean equals(Object obj):判断当前map和参数对象obj是否相等
//System.out.println(map.equals(map1));
//元视图操作的方法:遍历集合
// Set keySet():返回所有key构成的Set集合
System.out.println("------------------");
System.out.println("map的所有的key:");
Set keys = map.keySet();
for (Object key:keys) {
System.out.println(key+"->"+map.get(key));
}
// Collection values():返回所有value构成的Collection集合
System.out.println("map所有的value:");
Collection value = map.values();
Iterator iter = value.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
// Set entrySet():返回所有key
System.out.println("-------------------");
System.out.println("map所有的映射关系:");
Set mappings = map.entrySet();
for (Object mapping :mappings ){
Map.Entry entry = (Map.Entry) mapping;
System.out.println("key是"+entry.getKey()+",value是:"+entry.getValue());
}
}
}
6.1Map实现类之一:HashMap
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
一个key-value构成一个entry
所有的entry构成的集合是Set:无序的、不可重复的
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现
JDK1.8之前∶
JDK1.8之前HashMap底层是数组加链表结合在一起使用也就是链表散列,HashMap是通过key的HashCode经过扰动函数处理后得到的hash值。然后通过一种算法(n-1)&hash判断当前元素存放的位置(这里的n指的就是数组的长度)如果当前位置存在元素的话,就判断该元素与要存入的元素的hash值以及key是否相同,如果相同,直接覆盖。不相同就通过拉链法解决哈希冲突。
扰动函数:所谓的扰动函数指的就是HashMap中的hash()方法。使用扰动函数是为了防止一些实现比较差的hashcode()方法。使用扰动函数之后可以减少hash碰撞。
源码:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
拉链法:所谓拉链法就是将链表和数组相结合。也就是说创建一个链表数组,数组中的每一格就表示一
个链表。如果发生哈希冲突,则将冲突的值加到链表中即可。
JDK1.8之后在解决hash冲突时就有了较大的变化,当链表长度大于阈值(默认大小是8)时,将链表转
换为红黑数,以减少搜索时间。
6.2Map实现类之二:LinkedHashMap
LinkedHashMap 是 HashMap 的子类
-
在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序.
-
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插
入顺序一致.
示例:
import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; public class LinkedHashMapDemo { public static void main(String[] args) { HashMap hashMap = new HashMap(); hashMap.put(1,"张三"); hashMap.put(3,"李四"); hashMap.put(2,"王五"); System.out.println(hashMap.toString()); System.out.println("-------------------"); LinkedHashMap linkedHashMap = new LinkedHashMap(); linkedHashMap.put(1,"张三"); linkedHashMap.put(3,"李四"); linkedHashMap.put(2,"王五"); System.out.println(linkedHashMap.toString()); } }
6.3Map实现类之三:TreeMap
TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value
对处于有序状态。
TreeSet底层使用红黑树结构存储数据
TreeMap 的 Key 的排序:
**自然排序:**TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的
对象,否则将会抛出 ClasssCastException
**定制排序:**创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进
行排序。此时不需要 Map 的 Key 实现Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
7.Collections工具类
Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对
象设置不可变、对集合对象实现同步控制等方法
7.1常用的方法
排序操作:(均为static方法)
- reverse(List):反转 List 中元素的顺序.
- shuffle(List):对 List 集合元素进行随机排序.
- sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序.
- sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序.
- swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换.
7.2Collection与Collections的区别(面试题)
Collection是集合的上层接口,其有两个子接口一个是List,另一个是Set
Collections是集合中的一个工具类,里面提供了很多的方法供开发者调用。提高开发效率。
8.泛型
8.1为什么要有泛型?
泛型的设计背景
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之
前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,
其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计
成一个参数,这个类型参数叫做泛型。Collection,List,ArrayList 这个就是类型参数,即泛型。
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值
及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象
时)确定(即传入实际的类型参数,也称为类型实参)。
从JDK1.5以后,Java引入了“参数化类型(Parameterized type)”的概念,允许我们在创建集合时再指
定集合元素的类型,正如:List,这表明该List只能保存字符串类型的对象。
JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变
量、创建集合对象时传入类型实参。
8.2泛型在集合中的使用
8.2.1泛型在ArrayList中的使用
package collection;
import java.util.*;
public class GenericArrayListDemo {//Generic 泛型
public static void main(String[] args) {
//普通集合 Object类型
List list = new ArrayList();
list.add(18);
list.add("小王");
list.add(32.32);
//创建泛型之后的集合
List<String> list1 = new ArrayList<>();
//此时集合中只能存储String类型的数据,不能添加其他类型的数据
list1.add("小杨");
}
}
8.2.2泛型在HashMap中的使用
示例:
package collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class GenericHashMapDemo {
public static void main(String[] args) {
//创建泛型HashMap集合
HashMap<Integer,String> hashMap = new HashMap<>();
hashMap.put(1,"A");
hashMap.put(2,"B");
hashMap.put(3,"C");
hashMap.put(4,"D");
Set<Map.Entry<Integer, String>> entries = hashMap.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
System.out.println(entry.getKey() + "->" + entry.getValue());
}
}
}
8.3注意
泛型是JDK5.0出现的,在之前的版本中是不能使用的;
泛型是需要在一对<>中使用的;
做泛型的类型必须是引用类型,不能是基本数据类型,可以是基本数据类型的包装类
如果有多个泛型类型,使用因为逗号分隔。
8.4自定义泛型
8.4.1自定义泛型类
package collection;
public class GenericClassDemo {
public static void main(String[] args) {
//定义一个Animal对象 传入的数据类型是String类型
Animal<String> animal = new Animal<>("cat");
System.out.println(animal.getMessage());
//传入的数据类型是Integer类型
Animal<Integer> animal1 = new Animal<>(18);
System.out.println(animal1.getMessage());
}
}
//<T> T表示数据类型
class Animal<T>{
private T message;
public Animal(T message) {
this.message = message;
}
public Animal() {
}
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
@Override
public String toString() {
return "Animal{" +
"message=" + message +
'}';
}
}
8.4.2自定义泛型接口
示例:
package hw.test._25;
interface Persons<T>{
public T eat(T t);
}
//实现接口的第一种方式
class Person implements Persons<String>{
@Override
public String eat(String str) {
return str;
}
}
//实现接口的第二种方式
class Person1<T> implements Persons<T>{
@Override
public T eat(T t) {
return t;
}
}
public class Test_25_5 {
public static void main(String[] args) {
//第一种方式测试类
Persons<String> eating = new Person();
String str1 = eating.eat("我要吃肉");
System.out.println(str1);
//第二种方式测试类
Person1<String> eatings = new Person1<>();
String str2 = eatings.eat("我要吃西红柿");
System.out.println(str2);
}
}
8.5泛型通配符
import java.util.Arrays;
import java.util.List;
public class GenericDemo {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
MyClass.print(list);
System.out.println("---------------");
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
MyClass.print(doubles);
}
}
class MyClass {
public static void print(List<? extends Number> list){
for (Number num : list) {
System.out.println(num);
}
}
}
泛型中的符号:
T:表示类型
K:表示键key
V:表示值value
E:表示元素element