泛型
1、在定义一个类的方法时,因为不确定返回值类型,所以用一个符号代替,这个符号就是泛型
eg:ArrayList<Integer> list = new ArrayList<Integer>();
2、泛型的好处:
1、提高了数据的安全性,将运行时的问题提前暴露在编译阶段
2、避免了强转的麻烦
3、泛型类的定义 包含了泛型的类就是泛型类
格式:class 类名<泛型类型1,泛型类型2...>{
}
说明:
1.类名后面跟着的泛型类型,是泛型的声明,一旦泛型声明出,就相当于这个类型成了已知类型,这个类型可以在
整个类中使用。
2.泛型的声明需要一个合法的标识符即可。常用的大写字母:T W Q K V E
3.泛型的确定:将来在使用这个类创建对象的时候
4、练习 模拟栈和队列
import java.util.LinkedList; public class Demo03 { public static void main(String[] args) { MyStack<String,Integer> ms = new MyStack<String,Integer>(); ms.push("abc"); ms.push("aaaa"); ms.push("bbb"); while(!ms.isEmpty()) { System.out.println(ms.pop()); } } } class MyStack<T>{ private LinkedList<T> ll = new LinkedList<T>(); //添加元素 public void push(T t) { ll.addFirst(t); } //删除元素 public T pop() { //return ll.removeLast(); return ll.removeFirst(); } //判断为空 public boolean isEmpty() { return ll.isEmpty(); } }
5、泛型方法的定义
1、在方法声明中,带着泛型声明的方法,就是泛型方法
2、格式:修饰符<泛型声明1,泛型声明2....>返回值类型 方法名(参数列表){}
3、说明:
1.在方法上声明的类型,可以在整个方法中当做已知类型来使用。
2.如果非静态的方法没有任何泛型的声明,那么可以使用类中定义的泛型。
3.如果静态方法上没有任何的泛型的声明,那就不能使用类中定义的泛型。
6、泛型接口的定义与使用
1、带着泛型定义的接口
2、定义格式:interface 接口名称<泛型类型1...>{}
3、说明:
1.在接口声明上,定义好的泛型,作用范围整个接口。
2.泛型接口被其它类实现的时候,有两种实现方式:
1)声明的类不再是一个泛型类,而是一个确定了泛型的类。
2)声明的类还是一个泛型类,可以在创建对象的时候确定类型。
7、通配符
? extends E: E的类型以及子类类型
? super E:E的类型及其父类
Animal
|--Dog
|--YelloDog
method(? extends Animal)
method(? super Dog)
Set
1、Set是Collection的子接口
2、特点:无序、没有索引、不能重复
3、是接口,所以是抽象的,所以实现的子类,HashSet、TreeSet
4、HashSet特点:使用哈希表的存储方式存储元素,相同的元素无法存进集合,集合本身没有顺序,存储和取出的顺序不一致
5、Set集合的遍历:
第一种,转成数组,toArray(),不带泛型的数组,得到的是Object类型的数组
第二种,转成数组,toArray(T[] arr) 带泛型的数组,得到T类型的数组
当自己定义的数组大小小于集合时,会自动创建一个新的数组,将新数组返回
当自定义的数组大小大于等于集合时,不会自动创建,剩余位置用null填充,返回数组
第三种,使用迭代器 iterator()
第四种,增强for循环
格式:for (元素的数据类型 元素名称 : 要遍历的集合) {
使用元素名称代表当前访问的元素
}
本质:底层还是迭代器,在使用增强for循环时使用集合的功能会触发并发修改异常
使用增强for循环时无法修改元素
6、
/* * 随机生成10个20-40之间的随机数,存储在合适的集合中,并且进行遍历。 要求:随机数不能重复。 */ import java.util.HashSet; import java.util.Random; import java.util.Set; public class Demo01 { public static void main(String[] args) { Set<Integer> s = new HashSet<>(); Random r = new Random(); Integer a ; while(s.size()<10) { a = r.nextInt(21)+20; s.add(a); } for(Integer i:s) { System.out.println(i); } } }
/* * 键盘录入一个字符串,输出其中的字符,相同的字符只输出一次 */ import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class Demo04 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Set<Character> s = new HashSet<>(); String s1 =sc.nextLine(); for(int i=0;i<s1.length();i++) { s.add(s1.charAt(i)); } for(Character c:s) { System.out.print(c); } sc.close(); } }
7、HashSet如何使元素唯一
先比较元素的HashCode(),如果相同则再比较元素的equals()方法,如果还相同则认为一致,不添加此元素
想要修改可以在元素的类中重写这两个方法
import java.util.HashSet; public class Demo06 { public static void main(String[] args) { /* * 姓名和年龄全部一致为相同元素 * */ HashSet<Person> hs = new HashSet<Person>(); hs.add(new Person("jack",20)); hs.add(new Person("rose",30)); hs.add(new Person("wangwu",40)); hs.add(new Person("jack",20)); hs.add(new Person("zhaoli",21)); System.out.println(hs); } } class Person { String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return name+"..."+age; } @Override public int hashCode() { return name.hashCode()+age; } @Override public boolean equals(Object obj) { Person p = (Person)obj; return name.equals(p.name)&&age==p.age; } }
8、LinkedHashSet 是HashSet的子类,在元素存储的时候记录了元素的前后地址
特点:元素的存储取出顺序一致
9、TreeSet 元素的顺序按照字典顺序排列的集合,保证元素唯一性有两种
一种是让元素本身具有比较性 在元素类中继承Comparable接口,重写comparaTo方法
第二种是让集合具有比较性 比较器,继承Comparator接口,重写compara方法
/* * 对下列四位同学的成绩做降序排序,如果成绩一样, * 那在成绩排序的基础上按照年龄由小到大排序。 */ public class Homework4 { public static void main(String[] args) { TreeSet<Student> s = new TreeSet<>(); s.add(new Student("qq",20,80)); s.add(new Student("ww",22,60)); s.add(new Student("ee",22,70)); s.add(new Student("rr",21,60)); s.add(new Student("qq",20,40)); System.out.println(s); } } class Student implements Comparable<Student>{ private String name; private int age; private float score; public Student() {} public Student(String name, int age, float score) { super(); this.name = name; this.age = age; this.score = score; } 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; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } @Override public int compareTo(Student o) { if(score==o.score) { if(age==o.age) { return 0; }else if(age<o.age){ return -1; }else { return 1; } }else if(score<o.score) { return 1; }else { return -1; } } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", score=" + score + "]"; } }
import java.util.Comparator; import java.util.Set; import java.util.TreeSet; public class Homework7 { public static void main(String[] args) { // TODO Auto-generated method stub Set<Student> set = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // TODO Auto-generated method stub return o1.scoreAll-o2.scoreAll>=0?-1:1; } }); set.add(new Student("qq",30,89,56)); set.add(new Student("ww",57,90,78)); set.add(new Student("ee",35,99,56)); set.add(new Student("rr",78,77,57)); for(Student s:set) { System.out.println(s); } } } class Student{ String name; int score1; int score2; int score3; int scoreAll; public void setScoreAll() { scoreAll = score1+score2+score3; } public Student(String name, int score1, int score2, int score3) { super(); this.name = name; this.score1 = score1; this.score2 = score2; this.score3 = score3; setScoreAll(); } @Override public String toString() { return name + ", 语文" + score1 + ", 数学:" + score2 + ", 英语:" + score3 + ", 总分:" + scoreAll; } }