1.Collections集合工具类
public class Demo1 { public static void main(String[] args) { ArrayList<Person> list = new ArrayList<>(); list.add(new Person("小刘",16)); list.add(new Person("小爱",18)); list.add(new Person("小话",17)); Collections.sort(list, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } }); System.out.println(list); } } public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } @Override public String toString() { return "person{" + "age=" + age + ", name='" + name + '\'' + '}'; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }1.接口:Comparable接口
2.方法:int compareTo(T, o)->this-o(升序) o-this(降序)
public class Demo03 { public static void main(String[] args) { ArrayList<Student> list=new ArrayList<Student>(); list.add(new Student("小六",100)); list.add(new Student("小话",150)); list.add(new Student("小六",80)); Collections.sort(list); System.out.println(list); } }public class Student implements Comparable<Student>{ private String name; private Integer score; public Student() { } public Student(String name, Integer score) { this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getScore() { return score; } public void setScore(Integer score) { this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } @Override public int compareTo(Student o) { return this.getScore()-o.getScore(); } }Arrays中的静态方法:
static <T> List<T> asList(T...a) ->直接指定元素,转存到list集合中
public class Demo04 { public static void main(String[] args) { List<String> list = Arrays.asList("张三","李四"); System.out.println(list); } }2.泛型
1.泛型<>
2.作用
统一数据类型,防止将来的数据转换异常
3.注意:
a.泛型中的类型必须是引用数据类型
b.如果泛型不写默认是Object
1.为什么要使用泛型
1.从使用层面上来讲:
统一数据类型,防止将来的数据转换异常
2.定义层面上看:
定义带泛型的类、方法等,将来使用的时候给泛型确定什么类型,泛型就会变成什么类型,凡是涉及到泛型的都会变成确定的类型,代码更灵活
public class Demo01 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("1"); list.add(1); list.add("adc"); list.add(22); //获取元素中为String类型的字符串长度 for (Object o : list) { String s=(String) o; System.out.println(s.length());//ClassCastException } } }2.泛型的定义
2.1含有泛型的类
1.定义:
public class 类名<E>{
}
2.什么时候确定类型
new对象的时候
public class MyArrayList <E>{ //定义一个数组,充当ArrayList底层的数组,长度为10 Object[] obj =new Object[10]; //定义size,代表集合元素个数 int size; /** * 定义一个add方法,参数类型需要和泛型类型一致 * * 数据类型为E 变量名随便起 */ public boolean add(E e){ obj[size] =e; size++; return true; } /** * 定义一个get方法,根据索引获取元素 */ public E get(int index){ return (E) obj[index]; } @Override public String toString() { return "MyArrayList{" + "obj=" + Arrays.toString(obj) + ", size=" + size + '}'; } }public class Demo02 { public static void main(String[] args) { MyArrayList<String> list1=new MyArrayList<>(); list1.add("111"); list1.add("222"); System.out.println(list1);//直接输出list1,默认调用toString方法 } }2.2含有泛型的方法
1.格式:
修饰符 <E> 返回值类型 方法名(E e)
2.什么时候确定类型
调用的时候确定类型
public class ListUtils { //定义一个静态方法addAll,添加多个集合的元素 public static <E> void addAll(ArrayList<E> list,E ... e){ for (E e1 : e) { list.add(e1); } } }public class Demo3 { public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); ListUtils.addAll(list,"a","b"); System.out.println(list); } }2.3含有泛型的接口
1.格式
public interface 接口名<E>{
}
2.什么时候确定类型:
a.在实现类的时候还没有确定类型,只能在new实现类的时候确定类型了 ->ArrayList
b.在实现类就直接确定类型 ->比如Scanner
public interface MyList <E>{ public boolean add(E e); }public class MyArrayList1<E> implements MyList<E>{ //定义一个数组,充当ArrayList底层的数组,长度为10 Object[] obj =new Object[10]; //定义size,代表集合元素个数 int size; /** * 定义一个add方法,参数类型需要和泛型类型一致 * * 数据类型为E 变量名随便起 */ public boolean add(E e){ obj[size] =e; size++; return true; } /** * 定义一个get方法,根据索引获取元素 */ public E get(int index){ return (E) obj[index]; } @Override public String toString() { return "MyArrayList{" + "obj=" + Arrays.toString(obj) + ", size=" + size + '}'; } }public class Demo04 { public static void main(String[] args) { MyArrayList1<String> list1=new MyArrayList1<>(); list1.add("斩杀"); list1.add("斩杀"); list1.add("斩杀"); System.out.println(list1); } }public interface MyIterator <E>{ E next(); }public class MyScanner implements MyIterator<String>{ @Override public String next() { return "小刘和小莱"; } }public class Demo05 { public static void main(String[] args) { MyScanner myScanner=new MyScanner(); String reault =myScanner.next(); System.out.println("result = "+reault); } }3.泛型的高级使用
3.1泛型通配符?
public class Demo01 { public static void main(String[] args) { ArrayList<String> list1=new ArrayList<>(); list1.add("张三"); list1.add("李四"); ArrayList<Integer> list2=new ArrayList<>(); list2.add(111); list2.add(222); method(list1); method(list2); } private static void method(ArrayList<?> list) { for (Object o : list) { System.out.println(o); } } }3.2泛型的上限下限
1.作用:可以规定泛型的范围
2.上限:
a.格式:<? extends 类型>
b.含义:?只能接收extends后面的本类类型以及子类类型
3.下限:
a.格式:<? super 类型>
b.含义:?只能接收super后面的本类类型以及父类类型
/** * Integer ->Number ->Object * String ->Object */ public class Demo02 { public static void main(String[] args) { ArrayList<Integer> list1=new ArrayList<>(); ArrayList<String> list2=new ArrayList<>(); ArrayList<Number> list3=new ArrayList<>(); ArrayList<Object> list4=new ArrayList<>(); get1(list1); //get1(list2);错误 get1(list3); //get1(list4);错误 System.out.println("===================="); //get2(list1);错误 //get2(list2);错误 get2(list3); get2(list4); } //上限 ?只能接收extends后面的本类类型及子类类型 private static void get1(Collection<? extends Number> collection) { } //下限 ?只能接收super后面的本类类型及父类类型 private static void get2(Collection<? super Number> collection) { } }应用场景:
1.如果我们在定义类、方法、接口时,如果类型不确定,我们可以考虑定义含有泛型的类、方法、接口
2.如果类型不确定,但是能知道以后只能传递某个类的继承体系中的子类或父类,可以使用泛型中的通配符
3.斗地主案例(拓展案例)
3.1案例介绍
3.2案例分析
3.3代码实现
1.创建ArrayList集合->color ->专门存花色
2.创建ArrayList集合->number ->专门存牌号
3.创建ArrayList集合->poker ->专门存花色和牌号组合
4.打乱poker
5.创建4个ArrayList集合,分别代表三个玩家,以及一个存储一个底牌
6.如果index为最后三张,往底牌集合中存
7.如果index%3==0 给p1
8.如果index%3==1 给p2
9.如果index%3==2 给p3
10.遍历看牌
4.红黑树
集合中加入红黑树的目的:提高查询效率
HashSet集合:
数据结构:哈希表
jdk8之前:哈希表=数组+链表
jdk8之后:哈希表=数组+链表+红黑树->提高查询效率
5.Set集合
1.Set接口并没有对Collection接口进行功能上的扩充,而且所有的Set集合底层都是依靠Map实现
1.Set集合介绍
Set和Map密切相关
Map的遍历需要先变成单列集合,只能变成set集合
2.HashSet集合的介绍和使用
1.概述:HashSet是Set接口的实现类
2.特点:
a.元素唯一
b.元素无序
c.无索引
d.线程不安全
3.数据结构:哈希表
a.jdk8之前:哈希表 = 数组+链表
b.jdk8之后:哈希表 = 数组+链表+红黑树
加入红黑树目的:查询快
4.方法:和Collection一样
5.遍历:
a.增强for
b.迭代器
public class Demo01 { public static void main(String[] args) { HashSet<String> set=new HashSet<>(); set.add("li"); set.add("lihua"); set.add("lippp"); System.out.println(set); //迭代器 Iterator<String> integer=set.iterator(); while (integer.hasNext()){ System.out.println(integer.next()); } System.out.println("=============="); //增强for for (String s : set) { System.out.println(s); } } }3.LinkedHashSet集合的介绍和使用
1.概述:LinkedHashSet extends HashSet
2.特点:
a.元素唯一
b.元素有序
c.无索引
d.线程不安全
3.数据结构:
哈希表+双向链表
4.使用:和HashSet一样
public class Demo01 { public static void main(String[] args) { LinkedHashSet<String> set=new LinkedHashSet<>(); set.add("li"); set.add("lihua"); set.add("lippp"); System.out.println(set); //迭代器 Iterator<String> integer=set.iterator(); while (integer.hasNext()){ System.out.println(integer.next()); } System.out.println("=============="); //增强for for (String s : set) { System.out.println(s); } } }4.哈希值
1.概述:是由计算机算出来的一个十进制数,可以看作是对象的地址值
2.获取对象的哈希值,使用的是Object中的方法
public native int hashCode()
3.注意:如果重写了hashCode方法,那计算的就是对象内容的哈希值了
4.总结:
a.哈希值不一样,内容肯定不一样
b.哈希值一样,内容也有可能不一样
如果不重写hashCode方法,默认计算对象的哈希值
如果重写hashCode方法,计算对象内容的哈希值
5.字符串的哈希值是如何算出来的
问题:在计算哈希值的时候,有一个定值就是31,为啥?
31是一个质数,31这个数通过大量的计算,认为用31,可以尽量降低内容不一样但是哈希值一样的情况
内容不一样,哈希值一样(哈希冲突,哈希碰撞)
6.HashSet的存储去重复的过程
1.先计算元素的哈希值(重写hashCode方法),再比较内容(重写equals方法)
2.先比较哈希值,如果哈希值不一样,存
3.如果哈希值一样,再比较内容
a.如果哈希值一样,内容不一样,存
b.如果哈希值一样,内容也一样,去重复
7.HashSet存储自定义类型如何去重复?
总结:
1.如果HashSet存储自定义类型,如何去重复?
重写hashCode和equals方法,让HashSet比较属性的哈希值和属性的内容
2.如果不重写hashCode和equals方法,默认调用的是Object的,不同的对象肯定哈希值不一样,equals比较对象的地址值也不一样,所以此时即使对象的属性值一样,也不能去重复