泛型:
把明确的数据类型工作提前到编译时期,在创建集合的时候明确存储元素的类型。这样的做法有点像把数据类型当参数一样传递,所以泛型还有一个叫法:参数化类型
泛型语句的定义格式:
<引用数据类型>:注意尖括号里的数据类型只能是引用数据类型;
泛型的好处:
1、将我们运行时出现的问题提前到编译时期;
2、不需要做强制类型的转换;
3、优化了代码。消除了黄色警戒线,使代码看起来更简洁;
import java.util.ArrayList;
import java.util.Iterator;public class Generic1 {public static void main(String[] args) {//创建一个List集合对象//在JDK1.7之后,泛型会进行自动类型推断ArrayList<String> list = new ArrayList<>();//向集合中添加元素list.add("hello");list.add("hello");list.add("hello");list.add("hello");list.add("hello");
// list.add(20);
// list.add(12.34);
// list.add(new Student());//遍历
// Iterator iterator = list.iterator();
// while (iterator.hasNext()) {
// Object next = iterator.next();
//
// String s = (String) next; //ClassCastException
//
// System.out.println(next);
// }//遍历Iterator<String> iterator = list.iterator();while (iterator.hasNext()){String next = iterator.next();System.out.println(next);}}
}
泛型类:
把泛型定义在类上
格式:public class 类名<泛型类型1,,,,>
注意:泛型类型必须是引用类型
这里的<>里面的内容仅仅表示的是一种参数数据类型,参数类型是一种变量,既然是一种变量就要符合变量的命名规则,可以是任意符合标识符起名规则的名字。一般情况下在定义的时候,习惯用一个大写字符表示。
public class GenericTool1<T> {private T obj;public T getObj(){return obj;}public void setObj(T obj){this.obj = obj;}}
class GenericTest1 {public static void main(String[] args) {//如果不加泛型,默认使Object类型
// GenericTool1 gt1 = new GenericTool1();
//
// gt1.setObj("hello");
// gt1.setObj(20);
// gt1.setObj(12.34);GenericTool1<String> gt2 = new GenericTool1<>();gt2.setObj("hello");
// gt2.setObj(20);String obj = gt2.getObj();}
}
泛型方法:
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型....)
public class GenericTool2 {
// public void show(String s){
// System.out.println(s);
// }
//
// public void show(int i){
// System.out.println(i);
// }
//
// public void show(double d){
// System.out.println(d);
// }//用泛型方法改进,将来不确定要传入什么类型的数据public <F> void show(F f){System.out.println(f);}}
class GenericTest2 {public static void main(String[] args) {GenericTool2 genericTool2 = new GenericTool2();genericTool2.show("hello");genericTool2.show(10);genericTool2.show(12.34);}
}
泛型接口:
把泛型定义在接口上;
格式:public interface 接口名<泛型类型>
public interface GenericTool3<W> {public void show(W w);
}
class GenericTool3Impl<W> implements GenericTool3<W>{@Overridepublic void show(W w) {System.out.println(w);}
}
class GenericTest3 {public static void main(String[] args) {GenericTool3Impl<String> stringGenericTool3 = new GenericTool3Impl<>();stringGenericTool3.show("hello");
// stringGenericTool3.show(20);}
}
泛型通配符<?>:
任意类型,如果没有明确,那么就是Object以及任意的java类了。
?extends E:向下限定,及其子类
?super E:向上限定,及其父类
public class GenericDemo1 {public static void main(String[] args) {ArrayList<Animal> list1 = new ArrayList<Animal>();ArrayList<Dog> list2 = new ArrayList<Dog>();ArrayList<Object> list3 = new ArrayList<Object>();//泛型通配符<?>//任意类型,如果没有明确,那么就是Object以及任意的Java类了ArrayList<?> list4 = new ArrayList<Animal>();ArrayList<?> list5 = new ArrayList<Dog>();ArrayList<?> list6 = new ArrayList<Object>();//? extends E 向下限定,E及其子类ArrayList<? extends Animal> list7 = new ArrayList<Animal>();ArrayList<? extends Animal> list8 = new ArrayList<Dog>();ArrayList<? extends Animal> list9 = new ArrayList<Cat>();
// ArrayList<? extends Animal> lis10 = new ArrayList<Object>();//? super E 向上限定,E及其父类ArrayList<? super Animal> list11 = new ArrayList<Animal>();ArrayList<? super Animal> list13 = new ArrayList<Object>();
// ArrayList<? super Animal> list12 = new ArrayList<Dog>();}
}
class Animal{ }
class Dog extends day19.Animal {}
class Cat extends day19.Animal {}
静态导入:
语句定义格式:import static 包名,类名.方法名;
可直接导入到方法级别;
注意:方法必须是静态的;
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import static com.shujia.wyh.day19.StaticClass.fun;
import static com.shujia.wyh.day19.StaticClass.show;public class StaticImportDemo {public static void main(String[] args) {//MathSystem.out.println(Math.abs(-100));System.out.println(Math.pow(2,3));System.out.println(Math.max(100,200));//有没有什么方法,不同写类名,直接写方法名?
// System.out.println(abs(-200));//这时候,就需要静态导入的技术System.out.println(abs(-200));System.out.println(pow(2,4));fun();//当静态导入的方法名与本类中的方法名冲突的时候,调用的是本类中的方法show("spark");//如果此时我就是想使用静态导入的方法,怎么办?
// StaticClass.show("flink");//将前缀路径写完整com.shujia.wyh.day19.StaticClass.show("flink");//当静态导入的方法名与本类中的方法名冲突的时候,我们发现,直接通过类名调用的方式会更加简单//所以根据实际情况,选择使用静态导入}public static void show(String s){System.out.println("这是在StaticImportDemo类中的show方法"+s);}}
public class StaticClass {public static void fun(){System.out.println("数加科技,yyds");}public static void show(String s){System.out.println(s);}
}
set集合:
元素是唯一的,并且元素的顺序是无序的集合。
import java.util.HashSet;
import java.util.Set;public class SetDemo1 {public static void main(String[] args) {Set<String> set1 = new HashSet<>();//向集合中添加元素set1.add("hello");set1.add("world");set1.add("java");set1.add("bigdata");set1.add("hadoop");set1.add("world");set1.add("java");set1.add("hello");set1.add("spark");set1.add("spark");set1.add("hbase");set1.add("flink");set1.add("java");set1.add("hello");//遍历for(String s : set1){System.out.println(s);}
//flink
hallo
world
java
bigdata
spark
hadoop
hello
hbase}}
用set集合存储学生对象(当姓名和年龄一样时判断为同一个学生)
import java.util.Set;
import java.util.HashSet;public class Set2 {public static void main(String[] args) {Set<student1> student1s = new HashSet<>();student1 s1 = new student1("小飞", 18);student1 s2= new student1("小白", 17);student1 s3 = new student1("小祥", 19);student1 s4 = new student1("小飞", 18);student1s.add(s1);student1s.add(s2);student1s.add(s3);student1s.add(s4);for (student1 s:student1s){System.out.println(s);}
//student1{name='小白', age=17}
//student1{name='小祥', age=19}
//student1{name='小飞', age=18}}
}
class student1{private String name;private int age;public student1(){}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 student1(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;student1 student1 = (student1) o;if (age != student1.age) return false;return name != null ? name.equals(student1.name) : student1.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}@Overridepublic String toString() {return "student1{" +"name='" + name + '\'' +", age=" + age +'}';}
}
可变参数
格式:
修饰符 返回值类型 方法名(数据类型... 变量名){}
注意:这里的变量其实是一个数组,如果一个方法有可变参数,并且有多个参数,可变参数一定是最后一个参数。
即若使用可变参数定义方法时,有其他数据类型参与的时候,将可变参数的定义放在最后。
Arrays工具类中的一个方法:public static <T> List<T> asList(T... a)
该方法其实就是将数组转变为一个集合
代码举例:
import java.util.Arrays;
import java.util.List;public class ChangeDemo {public static void main(String[] args) {int a=1;int b=2;int c=4;sum(a,b);sum(a,b,c);sum("赵云",45,20,30);// Arrays工具类中的一个方法List<String> list = Arrays.asList("这是", "数组", "转变", "集合");for(String s : list){System.out.println(s);}}
// public static void sum(int a,int b){//求两个数的和
// System.out.println(a+b);
// }
// public static void sum(int a,int b,int c){//求三个数的和
// System.out.println(a+b+c);
// }
// 使用可变参数改进:含有多个参数,将可变参数放在最后public static void sum(String s,int... ints){int sum=0;for (int i : ints){sum+=i;}System.out.println(s+"的成绩总分为:"+sum);}
// 使用可变参数改进求几个数的和public static void sum(int... ints){int sum=0;for(int i : ints){sum+=i;}System.out.println(ints.length+"个数的和为:"+sum);}
}
注意:同一个方法定义中,可变参数只能出现一次:即不会出现如下代码行:
public static void sum(int... ints,int... ints2){}
LinkedHashSet:
public class HashSet<E> implements Set<E>
public class LinkedHashSet<E> extends HashSet<E> implemtents<E>
1、底层数据结构是哈希表和链表
2、哈希表保证元素的唯一
3、链表保证了元素的有序(存储和取出的顺序一致)
4、线程不安全,效率高
import java.util.LinkedHashSet;public class LinkedHashed1 {public static void main(String[] args) {LinkedHashSet<String> set1 = new LinkedHashSet<>();set1.add("hallo");set1.add("hello");set1.add("world");set1.add("java");set1.add("bigdata");set1.add("hadoop");set1.add("world");set1.add("java");set1.add("hello");set1.add("spark");set1.add("spark");set1.add("hbase");set1.add("flink");set1.add("java");set1.add("hello");for (String s:set1){System.out.println(s);}
// hallo
//hello
//world
//java
//bigdata
//hadoop
//spark
//hbase
//flink}
}
TreeSet:
底层结构是红黑树
元素唯一,元素可以按照某种规则进行排序
1、自然排序;
2、比较器排序;
A NavigableSet实现基于TreeMap的元件使用其有序natural,ordering,或由Comparator创建时提供,这取决于所使用的构造方法。
import java.util.TreeSet;public class TreeSet1 {public static void main(String[] args) {//创建TreeSet集合TreeSet<Integer> treeSet = new TreeSet<>();treeSet.add(20);treeSet.add(18);treeSet.add(24);treeSet.add(23);treeSet.add(88);treeSet.add(16);treeSet.add(12);treeSet.add(18);treeSet.add(20);treeSet.add(23);treeSet.add(1);treeSet.add(2);//遍历for(Integer i : treeSet){System.out.println(i);}
// 1
// 2
// 12
// 16
// 18
// 20
// 23
// 24
// 88// String s1 = "hello";
// String s2 = "hello";
// System.out.println(s1.compareTo(s2));}
}
存储学生对象并遍历:
由于我们这里TreeSet创建的时候,使用的是无参构造方法,走的是自然排序,而这里底层源码中有一步是向下转型的,Comparable<? super K>K=(Comparable<? super K>)key;
报错了
原因是我们Studeng3类没有实现Comparable接口,无法向下转型。
import java.util.Objects;public class Student1 implements Comparable<Student1> {private String name;private int age;public Student1() {}public Student1(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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student1 o) {
// 这里的返回值具体返回什么应该由我们自己来定义int i = this.age - o.age;int i2 = i == 0 ? this.name.compareTo(o.name) : i;return i2;}
}
测试类:
import java.util.TreeSet;public class Ttest2 {public static void main(String[] args) {TreeSet<Student1> students = new TreeSet<Student1>();Student1 s1 = new Student1("云", 19);Student1 s2 = new Student1("赵云", 18);Student1 s3 = new Student1("赵子龙", 20);Student1 s4 = new Student1("常山赵子龙", 21);Student1 s5 = new Student1("赵子龙", 20);students.add(s1);students.add(s2);students.add(s3);students.add(s4);students.add(s5);for (Student1 s : students){System.out.println(s);}}
}
这里是按年龄大小来排序的;
需求:使用TreeSet存储学生对象并以姓名的长度来排序
学生类:
import java.util.Objects;public class Student3 implements Comparable<Student3> {private String name;private int age;public Student3() {}public Student3(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;}@Overridepublic int compareTo(Student3 o) {
// 比较姓名的长度是否相等int i = this.name.length() - o.name.length();
// 若相等,比较姓名的内容是否相同int i2 = i == 0 ? this.name.compareTo(o.name) : i;
// 若相同,比较年龄是否相等int i3 = i2 == 0 ? this.age - o.age : i2;return i3;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
import java.util.TreeSet;public class Ttest3 {public static void main(String[] args) {TreeSet<Student3> students3 = new TreeSet<>();Student3 s1 = new Student3("yun", 19);Student3 s2 = new Student3("zhaoyun", 18);Student3 s3 = new Student3("zhaozilon", 20);Student3 s4 = new Student3("changshanzhaozilon", 21);Student3 s5 = new Student3("yun", 22);students3.add(s1);students3.add(s2);students3.add(s3);students3.add(s4);students3.add(s5);for(Student3 sc : students3){System.out.println(sc);}}
}
比较器排序:
利用TreeSet创建对象时的带参数的构造方法来进行比较器排序
TreeSet(Comparator<? super E> comparator)
构造一个新的,空的数集,根据指定的比较器进行排序
这里需要实现Comparator接口,重写compare()方法
代码举例:
实现Comparator接口的实现类ComparatorImpl:
import java.util.Comparator;public class ComparatorImpl implements Comparator<Student4> {@Overridepublic int compare(Student4 o1, Student4 o2) {
// 比较姓名的长度int i = o1.getName().length() - o2.getName().length();
// 比较姓名的内容int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
// 比较年龄的大小int i3 = i2 == 0 ? o1.getAge() - o2.getAge() : i2;return i3;}
}
import java.util.TreeSet;public class Ttest4 {public static void main(String[] args) {ComparatorImpl comparator = new ComparatorImpl();TreeSet<Student4> student4s = new TreeSet<>(comparator);//使用带参构造
// 创建学生对象Student4 s1 = new Student4("yun", 19);Student4 s2 = new Student4("zhaoyun", 18);Student4 s3 = new Student4("zhaozilon", 21);Student4 s4 = new Student4("chanshangzhaozilon", 20);Student4 s5 = new Student4("chanshangzhaoyun", 20);Student4 s6 = new Student4("zhaoyun", 22);Student4 s7 = new Student4("yun", 19);// 添加到集合student4s.add(s1);student4s.add(s2);student4s.add(s3);student4s.add(s4);student4s.add(s5);student4s.add(s6);student4s.add(s7);// 遍历for(Student4 student4 : student4s){System.out.println(student4);}}
}
总结:
自然排序使用无参构造创建对象,需要在元素类中实现Comparable接口,重写compareTo()方法
比较器排序使用带参构造创建对象,需要在元素类中实现Comparator接口,重写Compare()方法
比较器排序这里还可以使用匿名内部类进行comparator接口的实现:
import java.util.Comparator;
import java.util.TreeSet;public class Ttest4 {public static void main(String[] args) {
// ComparatorImpl comparator = new ComparatorImpl();
// TreeSet<Student4> student4s = new TreeSet<>(comparator);
// 使用匿名内部类改进:TreeSet<Student4> student4s = new TreeSet<>(new Comparator<Student4>() {@Overridepublic int compare(Student4 o1, Student4 o2) {
// 比较姓名的长度int i = o1.getName().length() - o2.getName().length();
// 比较姓名的内容int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
// 比较年龄的大小int i3 = i2 == 0 ? o1.getAge() - o2.getAge() : i2;return i3;}});Student4 s1 = new Student4("yun", 19);Student4 s2 = new Student4("zhaoyun", 18);Student4 s3 = new Student4("zhaozilon", 21);Student4 s4 = new Student4("chanshangzhaozilon", 20);Student4 s5 = new Student4("chanshangzhaoyun", 20);Student4 s6 = new Student4("zhaoyun", 22);Student4 s7 = new Student4("yun", 19);student4s.add(s1);student4s.add(s2);student4s.add(s3);student4s.add(s4);student4s.add(s5);student4s.add(s6);student4s.add(s7);for(Student4 student4 : student4s){System.out.println(student4);}}
}
集合的嵌套遍历:
需求:现在有某校有两个班的学生,每个班都有许多学生,每个学生都是一个对象
可以用一个集合表示一个班的学生
15班:ArrayList<Student> classList15
16班:ArrayList<Student> classList16
学校:ArrayList<ArrayList<Student>> school
import java.util.ArrayList;
import java.util.Iterator;public class ListQianTaotest {public static void main(String[] args) {ArrayList<Student2> classList15 = new ArrayList<>();ArrayList<Student2> classList16 = new ArrayList<>();ArrayList<ArrayList<Student2>> school = new ArrayList<>();school.add(classList15);school.add(classList16);Student2 s1 = new Student2("小白", 18);Student2 s2 = new Student2("小辉", 17);Student2 s3 = new Student2("小青", 16);Student2 s4 = new Student2("小芳", 20);//创建十六期的学生对象Student2 s11 = new Student2("小王", 18);Student2 s12 = new Student2("小李", 17);Student2 s13 = new Student2("小刘", 19);Student2 s14 = new Student2("小杨", 16);classList15.add(s1);classList15.add(s2);classList15.add(s3);classList15.add(s4);//将16期的学生对象添加到十六集合中classList16.add(s11);classList16.add(s12);classList16.add(s13);classList16.add(s14);for (ArrayList<Student2> clazz:school){System.out.println(clazz);}System.out.println("=========================================");for(int i = 0;i<school.size();i++){if(i==0){System.out.println("=============十五班:===================");for(int j =0 ;j<school.get(i).size();j++){Student2 student = school.get(i).get(j);System.out.println(student);}}else if(i==1){System.out.println("=============十六班:===================");for(int j =0 ;j<school.get(i).size();j++){Student2 student = school.get(i).get(j);System.out.println(student);}}}System.out.println("========================================================");//迭代器遍历Iterator<ArrayList<Student2>> iterator = school.iterator();while (iterator.hasNext()){ArrayList<Student2> clazz = iterator.next();Iterator<Student2> iterator1 = clazz.iterator();while (iterator1.hasNext()){Student2 student = iterator1.next();System.out.println(student);}}}
}
class Student2{private String name;private int age;public Student2(){}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 Student2(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student2{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student2 student2 = (Student2) o;if (age != student2.age) return false;return name != null ? name.equals(student2.name) : student2.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
}
测试自己定义的集合类底层是Linkedlist:
public class MyStackTest {public static void main(String[] args) {//创建自己定义的集合类MyStack myStack = new MyStack();//添加元素到集合myStack.myAdd("hello");myStack.myAdd("world");myStack.myAdd("java");myStack.myAdd("bigdata");// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet()); //NoSuchElementException//应该在获取元素之前判断集合中还有没有元素while (!myStack.myIsEmpty()){Object o = myStack.myGet();System.out.println(o);}}}
import java.util.LinkedList;public class MyStack {private LinkedList linkedList;MyStack(){linkedList = new LinkedList();}public void myAdd(Object obj){linkedList.addFirst(obj);}public Object myGet(){
// return linkedList.getFirst();return linkedList.removeFirst();}
增强for循环:
概述:简化数组和collection的概述;
格式:for(元素数据类型 变量名:数组或者collection){
使用变量即可,该变量就是元素
}
import java.util.ArrayList;
import java.util.ListIterator;public class For {public static void main(String[] args) {//定义一个数组int[] arr = {1,2,3,4,5};//普通for循环遍历// for(int i=0;i<arr.length;i++){// System.out.println(arr[i]);// }// System.out.println("使用增强for循环遍历数组:");// for(int num : arr){// System.out.println(num);// }System.out.println("=======================================");ArrayList<String> strings = new ArrayList<>();strings.add("hello");strings.add("world");strings.add("java");strings.add("bigdata");strings.add("hadoop");for(String string : strings){System.out.println(string);
// hello
// world
// java
// bigdata
// hadoop }// strings = null;
// for(String string : strings){ //NullPointerException
// System.out.println(string);
// }//我们应该在遍历之前判断一下是不是null
// if(strings!=null){
// for(String string : strings){
// System.out.println(string);
// }
// }else {
// System.out.println("该集合为null");
// }//其实增强for循环就是用来替代迭代器的//怎么去验证它就是用来替代迭代器的呢?//使用并发修改异常去验证
// for(String s : strings){
// //ConcurrentModificationException
// if("java".equals(s)){
// strings.add("spark");
// }
// }ListIterator<String> iterator = strings.listIterator();while (iterator.hasNext()){String next = iterator.next();if("java".equals(next)){iterator.add("spark");}}System.out.println(strings);
// [hello, world, java, spark, bigdata, hadoop]}
}