文章目录续上一节Java集合框架,Collection接口,List接口与实现类,依旧是Java集合的内容。
- 4 泛型
- 4.1 泛型类
- 4.2 泛型接口
- 4.3 泛型方法
- 4.4 泛型集合
- 4.5 测试类
- 5 Set接口与实现类
- 5.1 HashSet类
- 5.2 TreeSet类
- 5.2.1 Comparable接口
- 5.2.2 Comparator比较器
- Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。
【类似于模板,先不定义类型,在使用时在限定类型。比如同一个泛型方法,可以用于整数和都浮点数运算】 - 这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
- 语法:
T称为类型占位符,表示一种引用类型。可以写多个参数,逗号隔开 - 运用泛型的好处:
(1)提高代码的重用性
(2)防止类型转换异常,提高代码的安全性
- 泛型类创建语法:类名
- 可以创建变量T t;但是不能实例化T t1 = new T();(有可能构造函数私有等原因)
- 泛型只能使用引用类型【可以是Integer,不能是int】
- 不同泛型类型对象之间不能相互赋值。
package study.generic; //定义泛型类语法:类名4.2 泛型接口public class MyGenericClass { //1.使用泛型类创建成员变量 T t; //T t2 = new T();//编译报错:类型参数'T'不能直接实例化 //2.作为方法形式参数 public void show(T t){ System.out.println("泛型参数:"+t); } //3.作为返回值 public T getT(){ return t; } }
- 泛型接口语法:接口名
- 不能泛型静态常量。
泛型接口:
package study.generic; public interface MyGenericIn{ // T t;//编译报错:不能从静态上下文引用 String name = "louis"; //接口只有规范,不写方法体 T service(T t); }
泛型接口的两种实现类:
- 继续使用泛型
package study.generic; public class InClass1implements MyGenericIn { @Override//重写快捷键【Alt+Insert】 public T service(T t) { return t; } }
- 在实现类中指定类型
package study.generic; public class InClasses4.3 泛型方法implements MyGenericIn { @Override public String service(String string) { return string; } }
- 定义在普通类中,泛型方法的语法修饰符
返回类型 方法名(T t)
普通类中的泛型方法:
package study.generic;
//普通类
public class GenMethodClass {
//泛型方法
public void show(T t){
System.out.println("泛型方法" + t);
}
public T show2(T t){
System.out.println("泛型方法" + t);
return t;
}
}
4.4 泛型集合
- 概念:参数化类型、类型安全的集合。强制集合元素的类型必须一致,可以避免强制类型转换时出错。
- 特点:
(1)编译时即可检查,而非运行时抛出异常
(2)访问时,不必类型转换(拆箱)
(3)不同泛型之间应用不能相互赋值,泛型不存在多态
普通集合:
泛型集合:
package study.generic;
import java.util.ArrayList;
public class mainGenericText {
public static void main(String[] args) {
System.out.println("1.泛型类");
MyGenericClass c1 = new MyGenericClass();
c1.t = "Hello,Java";
c1.show("Hello,World");
System.out.println(c1.getT());
MyGenericClass c2 = new MyGenericClass<>();
c2.show(250);
// MyGenericClass c3 = new MyGenericClass();//编译报错:类型参数不能是原始类型
// c2 = c1;//不同类ing不能互相赋值
System.out.println("2.泛型接口的实现类调用");
//需要指名泛型类
InClass1 c3 = new InClass1<>();
System.out.println(c3.service(30));
//已定义好的接口实现类
InClasses
5 Set接口与实现类
- 特点:无序、无下标、元素不可重复
- 方法:全部继承自Collection中的方法。
增、删、遍历、判断完全一致。
构造方法因为实现类不同略有不同Sets1 = new HashSet<>();。 - 两种实现类:HashSet和TreeSet。
- 存储结构:哈希表(数组+链表+红黑树)
- 存储过程(怎么判断元素是否重复):
①根据hashCode方法计算保存的位置,如果位置为空,直接保存;
②若不为空,再执行equals方法,如果equals为true,则认为是重复,否则形成链表。
【对于自定义类,需要重写方法】例如Person类(属性名字、年龄)
- 特点
基于HashCode计算元素存放位置:
(1)利用31这个质数,减少散列冲突;
(2)提高执行效率。31*i=(i << 5)-i转为移位操作。
当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入 - 方法(同Collection)
- 存储结构:红黑树(二叉排序平衡)
- 创建集合:TreeSet
treeSet = new TreeSet<>() - 方法(添加、删除、遍历、判断同Collection)
- 特点:
(1)基于排列顺序实现元素不重复。
(2)实现SortedSet接口,对集合元素自动排序。
(3)元素对象的类型必须实现Comparable接口,指定排序规则。
(4)通过CompareTo方法确定是否为重复元素。
查源码知道,包类型都自动继承Comparable接口,并且Comparable接口里面只有一个方法CompareTo方法。 - TreeSet集合的使用方法(自定义排序规则)
(1)对象类型继承Comparable接口,重写CompareTo方法来制定排序规则。
(2)Comparator比较器实现定制比较.
int compareTo(T o)将此对象与指定的对象进行比较,返回一个负整数、零或一个正整数,因为这个对象小于、等于或大于指定的对象。
重写对象方法:
package generic; public class Person implements Comparable{ String name; 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) { int n1 = this.getName().compareTo(o.getName()); int n2 = this.getAge()-o.getAge(); return n1==0?n2:n1; } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + '}'; } }
创建集合并添加对象:
package generic;
import java.util.TreeSet;
public class TreeSetText {
public static void main(String[] args) {
//创建集合
TreeSet pe = new TreeSet<>();
//创建对象
Person p1 = new Person("Louis", 22);
Person p2 = new Person("LV", 20);
Person p3 = new Person("Chanel", 19);
//添加对象到集合
pe.add(p1);
pe.add(p2);
pe.add(p3);
pe.add(new Person("LV", 20));//因为重写了比较方法才可以判断出重复
System.out.println(pe.toString());
//删除对象
pe.remove(p1);
pe.remove(new Person("LV", 20));//因为重写了比较方法才可以判断出重复存在
System.out.println(pe.toString());
}
}
5.2.2 Comparator比较器
Comparator实现定制比较(比较器),就可以不再需要实现Comparable接口比较功能。
package generic;
import java.util.Comparator;
import java.util.TreeSet;
public class Demo01 {
public static void main(String[] args) {
//创建集合并使用comparator接口定制比较
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length()-o2.length();
int n2 = o1.compareTo(o2);
return n1==0?n2:n1;//长度相等判断再是否一致
}
});
ts.add("Balenciaga");
ts.add("Chanel");
ts.add("Louis");
ts.add("Burberry");
System.out.println(ts);//[Louis, Chanel, Burberry, Balenciaga]
}
}



