前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
220. 集合体系结构
221. collection集合的概述和使用
collect
是单列集合的顶层接口,他表示一组对象,这些对象也成为Collection
元素。
JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set
和List
)实现。
创建Collection
集合的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package Collection演示;import java.util.ArrayList;import java.util.Collection;public class CollectionDemo { public static void main (String[] args) { Collection<String> c = new ArrayList<String>(); c.add("hello" ); c.add("world" ); System.out.println(c); } }
222.Collection集合的常见用法
方法名
说明
boolean add(E e)
添加元素
boolean remove(Object o)
从集合中移除指定的元素
void clear()
清空集合中的元素
boolean contains(Object o)
判断集合中是否存在指定元素
boolean isEmpty()
判断集合是否为空
int size()
集合的长度,也就是集合中元素的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package Collection演示;import java.util.ArrayList;import java.util.Collection;public class CollectionDemo2 { public static void main (String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c.add("Hello" )); c.add("World" ); c.add("World" ); System.out.println(c); c.remove("World" ); c.remove("asdasd" ); System.out.println(c); boolean flag = c.contains("Hello" ); System.out.println(flag); c.clear(); System.out.println(c); System.out.println(c.isEmpty()); } }
223.Collection集合的遍历
Iterator
: 迭代器,集合的专用遍历方式。他是依赖于集合的存在。("一个一个找元素"器)
迭代器的方法:
E next()
: 返回迭代中的下一个元素。
boolean hasNext()
: 如果迭代具有更多元素,则返回true
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package Collection演示;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class CollectionDemo3 { public static void main (String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c.add("Hello" )); c.add("World" ); c.add("java" ); Iterator<String> it = c.iterator(); while (it.hasNext()){ String s =it.next(); System.out.println(s); } } }
224.集合使用步骤图解
说白了就是指针。
225.collection集合存储学生对象并遍历
和之前那个Arraylist
项目差不多,不同的是collection
集合可以使用迭代器遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package Collection集合存储学生对象;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class test { public static void main (String[] args) { Student s1 = new Student("林青霞" , "30" ); Student s2 = new Student("张曼玉" , "14" ); Student s3 = new Student("王祖贤" , "18" ); Collection<Student> c = new ArrayList<>(); c.add(s1); c.add(s2); c.add(s3); Iterator<Student> it = c.iterator(); while (it.hasNext()) { Student s = it.next(); System.out.println(s.getName() + s.getAge()); } } }
226.list集合
list
继承自collection
集合,collection
集合中的功能都能用。
list
是有序集合,并且它允许重复的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package list集合;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class listDemo1 { public static void main (String[] args) { List<String> list = new ArrayList<>(); list.add("hello" ); list.add("world" ); list.add("world" ); System.out.println(list); Iterator<String> it = list.iterator(); while (it.hasNext()){ System.out.println(it.next()); } } }
227.list集合特有功能
这些功能,他的父类collection
没有,但是子类ArrayList
有。
这些方法是:
方法
作用
void add(int index, E element)
在指定位置插入元素
E remove(int index)
删除指定索引处的元素
E set(int index, E element)
修改指定索引处的元素,返回被修改的元素
E get(int index)
返回指定索引处的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package list集合;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class listDemo1 { public static void main (String[] args) { List<String> list = new ArrayList<>(); list.add("hello" ); list.add("world" ); list.add("world" ); list.add(2 , "nihao" ); System.out.println(list); list.remove(3 ); System.out.println(list); System.out.println(list.set(1 , "JaveA" )); System.out.println(list); System.out.println(list.get(1 )); int j = list.size(); for (int i = 0 ; i < j; i++) { System.out.println(list.get(i)); } } }
228.list集合存储学生对象并遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package list存储学生对象;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class ListDemo { public static void main (String[] args) { Student s1 = new Student("林青霞" , "30" ); Student s2 = new Student("风清扬" , "29" ); Student s3 = new Student("左冷禅" , "28" ); List<Student> l = new ArrayList<Student>(); l.add(s1); l.add(s2); l.add(s3); Iterator<Student> iterator = l.iterator(); while (iterator.hasNext()) { Student s = iterator.next(); System.out.println(s.getName() + "," + s.getAge()); } System.out.println("--------------" ); for (int i = 0 ; i < l.size(); i++) { System.out.println(l.get(i).getName() + "," + l.get(i).getAge()); } } }
229.并发修改异常
说人话总结: 使用迭代器进行迭代的时候不能增加和减少元素的个数。
比如,老板叫迭代器去搬十块砖。迭代器接到命令就去干活了。等到搬到第八块砖的时候迭代器接到老板电话,说改要求需要他去搬十一块砖了。
这和迭代器一开始签的搬十块砖的合同不一样,违约了。迭代器一生气不干了!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package list集合;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class listDemo1 { public static void main (String[] args) { List<String> list = new ArrayList<>(); list.add("hello" ); list.add("world" ); list.add("java" ); for (int i=0 ; i<list.size();i++){ String s =list.get(i); if (s.equals("world" )){ list.add("javaee" ); } } System.out.println(list); } }
230.列表迭代器
ListIterator
:列表迭代器
通过List
集合的listIterator()
方法得到,所以说它是list
集合特有的迭代器。
用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package list集合;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.ListIterator;public class listDemo1 { public static void main (String[] args) { List<String> list = new ArrayList<>(); list.add("hello" ); list.add("world" ); list.add("java" ); ListIterator<String> lit = list.listIterator(); while (lit.hasNext()){ String s = lit.next(); if (s.equals("world" )) { lit.add("javaee" ); } } System.out.println(list); } }
ListIterator
和Iterator
功能大致相同,都有hasnext
和next
。
但是ListIterator
的add
功能不会有并发修改异常。
231.增强for循环
增强for :简化List
和Collection
集合的遍历
实现Iterable
接口的类允许其对象成为增强型for
语句的目标
它是JDK5之后出现的。其内部原理是一个Iterator
迭代器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package 增强for ;import java.util.ArrayList;import java.util.List;public class ForDemo { public static void main (String[] args) { int [] arr = {1 , 3 , 6 , 7 , 9 }; for (int i : arr) { System.out.println(i); } String[] arr2 = {"hello" , "world" , "java" }; for (String s : arr2){ System.out.println(s); } List<String> list = new ArrayList<String>(); list.add("hello" ); list.add("world" ); list.add("java" ); for (String s: list){ if (s.equals("world" )){ list.add("javaee" ); } } System.out.println(list); } }
很奇怪,老师说for
增强循环内核是Iterator
迭代器,可是我并没有抛出并发错误……
后来才发现原来我的list
中是没有world
的,那if
语句就不执行,就不报错了。
232.list集合存储学生对象用三种方式遍历
三种方式分别为:Iterator
,for
,增强for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package list学生对象三种遍历;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class listDemo { public static void main (String[] args) { Student s1 = new Student("林青霞" , "21" ); Student s2 = new Student("张曼玉" , "19" ); List<Student> l = new ArrayList<Student>(); l.add(s1); l.add(s2); Iterator<Student> it = l.iterator(); while (it.hasNext()) { Student s = it.next(); System.out.println(s.getName() + "," + s.getAge()); } for (int i = 0 ; i < l.size(); i++) { Student s = l.get(i); System.out.println(s.getName() + "," + s.getAge()); } for (Student s : l){ System.out.println(s.getName() + "," + s.getAge()); } } }
一般来说就用for
就够了。iterator
不咋常用。
233.数据结构之栈和队列
栈:
一端开口,先进后出。
队列:
数据从后端 进入队列模型的过程称为:入队列
数据从前端 离开队列模型的过程称为:出队列
队列两端开口,先进先出。
234.数据结构之数组和链表
数组:查询快,增删慢的模型。
查询数据通过索引定位,查询任意数据耗时相同,查询效率高。
删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低。
添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低。
链表:节点的存储位置(地址)
链表的一个节点包含了这个节点的地址、数据、下一个节点的地址。
链表是一种增删快的模型(对比数组)
链表是一种查询慢的模型(对比数组)。因为查询数据D是否存在必须从头节点开始查。
235.list集合的子类特点
ArrayList
和LinkedList
,底层数据结构一个是数组一个是列表。 用法和List
一样的。(因为是继承)
练习:使用ArrayList
和LinkedList
使用三种方法存储字符串并遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package 数组与链表;import java.util.ArrayList;import java.util.Iterator;import java.util.LinkedList;public class test { public static void main (String[] args) { ArrayList<String> al = new ArrayList<>(); al.add("林青霞" ); al.add("张曼玉" ); al.add("王祖贤" ); System.out.println(al); Iterator<String> it = al.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } for (int i =0 ; i < al.size(); i++){ String s = al.get(i); System.out.println(s); } for (String s : al){ System.out.println(s); } LinkedList<String> ll = new LinkedList<>(); ll.add("学雷锋" ); ll.add("做好事" ); ll.add("不留名" ); Iterator<String> itr = ll.iterator(); while (itr.hasNext()){ String s = itr.next(); System.out.println(s); } for (int i =0 ; i < ll.size(); i++){ String s = ll.get(i); System.out.println(s); } for (String s : ll){ System.out.println(s); } } }
236.ArrayList存储学生对象三种遍历
太简单了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package 数组与链表;import 存储学生对象并遍历.Student;public class Rewrite extends Student { public Rewrite () { } public Rewrite (String name, String age) { super (name, age); } @Override public String toString () { return "姓名是" + getName() + "年龄是" + getAge(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package 数组与链表;import 存储学生对象并遍历.Student;import java.util.ArrayList;import java.util.Iterator;import java.util.LinkedList;public class test { public static void main (String[] args) { Rewrite s1 = new Rewrite("林青霞" ,"20" ); Rewrite s2 = new Rewrite("张曼玉" ,"19" ); Rewrite s3 = new Rewrite("郭子维" ,"17" ); ArrayList<Rewrite> al = new ArrayList<>(); al.add(s1); al.add(s2); al.add(s3); System.out.println(al); System.out.println("----------------------" ); Iterator<Rewrite> it = al.iterator(); while (it.hasNext()){ Rewrite s = it.next(); System.out.println(s); } System.out.println("----------------------" ); for (int i =0 ; i < al.size(); i++){ Rewrite s = al.get(i); System.out.println(s); } System.out.println("----------------------" ); for (Student s : al){ System.out.println(s); } } }
为了输出方便,重写了toString
方法。
237.LinkedList的特有方法
方法名
说明
public void addFirst(E e)
在该列表的开头插入指定的元素
public void addLast(E e)
在该列表的结尾插入指定的元素
public E getFirst()
返回此列表中的第一个元素
public E getFirst()
返回此列表中的最后一个元素
public E removeFirst()
从此列表中删除并返回第一个元素
public E removeLast()
从此列表中删除并返回最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package 链表集合特有方法;import java.util.LinkedList;public class LinkedListDemo { public static void main (String[] args) { LinkedList<String> ll = new LinkedList<>(); ll.add("林青霞" ); ll.add("张曼玉" ); ll.add("王祖贤" ); ll.addFirst("开头" ); System.out.println("方法1" +ll); ll.addLast("结尾" ); System.out.println("方法2" +ll); System.out.println("方法3" +ll.getFirst()); System.out.println("方法4" +ll.getLast()); System.out.println("方法5" +ll.removeFirst()); System.out.println(ll); System.out.println("方法6" +ll.removeLast()); System.out.println(ll); } }
238.Set集合概述和特点
set
集合特点不包含重复的元素,没有带索引的方法,不可以使用for
循环遍历。
HashSet
对集合的迭代顺序不做任何的保证。
使用Set
和Set
的子类,拓展名要装箱 !而String
默认已经装箱。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.HashSet;import java.util.Set;public class SetDemo { public static void main (String[] args) { Set<String> s = new HashSet<>(); s.add("林青霞" ); s.add("风清扬" ); s.add("李冰冰" ); s.add("李冰冰" ); for (String i: s){ System.out.println(i); } } }
239.哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。
Object
类中有一个方法可以获得对象的哈希值。
public int hashCode()
: 返回对象的哈希码值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package 获取哈希值;import 存储学生对象并遍历.Student;public class HashDemo { public static void main (String[] args) { Student s1 = new Student("林青霞" , "12" ); System.out.println(s1.hashCode()); System.out.println(s1.hashCode()); Student s2 = new Student("林青霞" , "12" ); System.out.println(s2.hashCode()); System.out.println("hello" .hashCode()); System.out.println("world" .hashCode()); System.out.println("world" .hashCode()); System.out.println("重地" .hashCode()); System.out.println("通话" .hashCode()); System.out.println("我的" .hashCode()); } }
为什么“重地”和“通话”哈希码相同?因为哈希值是有范围的,汉字是无限的。没办法超出编制了,只能发重复哈希码。
相同的对象哈希码相同。
240.哈希set集合的概述和特点
底层数据结构是哈希表。
对集合迭代顺序不做保证
没有带索引的方法,不能用普通for
循环
不包括重复元素
补充:个人认为HashSet
和Set
相比优势在于可以自定义什么是“重复数据”。 而且Set
也得用HashSet
的多态形式实现。属于是一个特例?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package Hashset;import java.util.HashSet;public class HashSetDemo { public static void main (String[] args) { HashSet<String> hs = new HashSet<>(); hs.add("林青霞" ); hs.add("风清扬" ); hs.add("王冰冰" ); hs.add("王冰冰" ); System.out.println(hs); for (String s : hs){ System.out.println(s); } } }
241.HashSet集合保证元素唯一性的源码分析
没看懂 后面再说吧
242.常见数据结构之哈希表
哈希表默认长度为16。
拉链法解决哈希冲突:
先哈希值对16取余,算出地址(即需要存储在哪一个格子中)
再判断该位置是否已经有元素了。
该位置没有元素,那这个元素就是第一个元素
该位置有元素了,比较哈希值。如果哈希值不相同,那以链表的形式添加这个元素。
哈希值也相同,调用qual()
方法比较元素内容。元素内容不相同,添加这个元素
元素内容相同,不添加
解决了上节的疑惑!
243.HashSet集合存储学生对象并遍历
和之前的项目相同。但是如果学生对象的成员变量相同,那就认为是同一个对象。
思路:
定义学生类。
创建HashSet
集合对象
创建学生对象
把学生添加到集合
遍历集合(增强for)
在学生类中重写两个方法hashCode()
和equals()
自动生成即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package 存储学生对象并遍历;public class Student { private String name; private String age; public String getName () { return name; } public void setName (String name) { this .name = name; } public String getAge () { return age; } public void setAge (String age) { this .age = age; } public Student () { }; public Student (String name, String age) { this .name = name; this .age = age; }; public void show () { System.out.println("名字是" +name+",年龄是" +age); } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Student student = (Student) o; if (name != null ? !name.equals(student.name) : student.name != null ) return false ; return age != null ? age.equals(student.age) : student.age == null ; } @Override public int hashCode () { int result = name != null ? name.hashCode() : 0 ; result = 31 * result + (age != null ? age.hashCode() : 0 ); return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package Hashset;import 存储学生对象并遍历.Student;import java.util.HashSet;public class StudentDemo { public static void main (String[] args) { Student s1 = new Student("林青霞" , "张曼玉" ); Student s2 = new Student("黄祯" , "23" ); Student s3 = new Student("我爱罗" , "99" ); Student s4 = new Student("黄祯" , "23" ); HashSet<Student> hs = new HashSet<>(); hs.add(s1); hs.add(s2); hs.add(s3); hs.add(s4); for (Student s : hs) { System.out.println(s.getName() + "," + s.getAge()); } } }
244.LinkedHashSet集合概述和特点
哈希表和链表实现的Set
接口,具有可预测的迭代次序。
由链表保证元素有序,也就是说元素的存储和取出顺序是一致的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.LinkedHashSet;public class LinkedHashSetDemo { public static void main (String[] args) { LinkedHashSet<String> lhs = new LinkedHashSet<>(); lhs.add("hello" ); lhs.add("world" ); lhs.add("java" ); for (String s:lhs){ System.out.println(s); } lhs.add("java" ); for (String s:lhs){ System.out.println(s); } } }
245.TreeSet集合概述和特点
元素有序,不是存储和取出的排序,而是根据构造方法排序。
TreeSet()
: 根据其元素的自然排序进行排序
TreeSet(Comparator comparator)
:根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for
循环遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package TreeSet;import java.util.TreeSet;public class TreeSetDemo { public static void main (String[] args) { TreeSet<Integer> ts = new TreeSet<Integer>(); ts.add(10 ); ts.add(20 ); ts.add(50 ); ts.add(40 ); ts.add(30 ); ts.add(30 ); System.out.println(ts); for (Integer i : ts){ System.out.println(i); } } }
246.Comparable的使用
首先,要想对一个TreeSet
的内部元素排序,默认的包装类是可以的。但是如果这个包装类是自己定义的类(比如Student
),就必须让这个自定义类实现Comparable
接口。
实现接口后,通过重写CompareTo(T o)
方法实现比较。注意实现接口的时候要注明接口的泛型<NewStudent>
!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package TreeSet;import 存储学生对象并遍历.Student;public class NewStudent extends Student implements Comparable <NewStudent > { public NewStudent () { } public NewStudent (String name, String age) { super (name, age); } @Override public int compareTo (NewStudent s) { int thisAge = Integer.parseInt(this .getAge()); int Age = Integer.parseInt(s.getAge()); int num1 = thisAge-Age; int num2 = num1 == 0 ? this .getName().compareTo(s.getName()):num1; return num2; } @Override public String toString () { return getName()+"," +getAge(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package TreeSet;import java.util.TreeSet;public class ComparableDemo { public static void main (String[] args) { NewStudent s1 = new NewStudent("Qingxia Lin" ,"21" ); NewStudent s2 = new NewStudent("Qingyang Feng" ,"18" ); NewStudent s3 = new NewStudent("Jiangeng Sun" ,"19" ); NewStudent s4 = new NewStudent("Wong Zing" , "19" ); TreeSet<NewStudent> ts = new TreeSet<NewStudent>(); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); for (NewStudent ns: ts){ System.out.println(ns); } } }
247.比较器Comparator的使用
和Comparable
差不多作用。这个是在测试类直接用内部类的形式使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package TreeSet;import 存储学生对象并遍历.Student;import java.util.Comparator;import java.util.TreeSet;public class ComparatorDemo { public static void main (String[] args) { TreeSet<NewStudent> ts = new TreeSet<NewStudent>(new Comparator<NewStudent>() { @Override public int compare (NewStudent s1, NewStudent s2) { int s1Age = Integer.parseInt(s1.getAge()); int s2Age = Integer.parseInt(s2.getAge()); int num1 = s1Age - s2Age; int num2 = num1 == 0 ? s1.getName().compareTo(s2.getName()):num1; return num2; } }); NewStudent s1 = new NewStudent("Qingxia Lin" ,"21" ); NewStudent s2 = new NewStudent("Qingyang Feng" ,"18" ); NewStudent s3 = new NewStudent("Jiangeng Sun" ,"19" ); NewStudent s4 = new NewStudent("Wong Zing" , "19" ); NewStudent s5 = new NewStudent("Wong Zing" , "19" ); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); for (NewStudent ns: ts){ System.out.println(ns); } } }
小结: 比较和比较器用来比较包装好的对象比较好用。基本类型比较(比如int数组中元素排序)还是用sort
排好一点。
248.成绩排序
对小学生(名字语文成绩数学成绩)进行排序。需求:总分由高到低。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package 成绩排序;public class Student implements Comparable <Student > { private String name; private int ChineseScore; private int MathScore; public Student (String name, int chineseScore, int mathScore) { this .name = name; ChineseScore = chineseScore; MathScore = mathScore; } public Student () { } ; public String getName () { return name; } public void setName (String name) { this .name = name; } public int getChineseScore () { return ChineseScore; } public void setChineseScore (int chineseScore) { ChineseScore = chineseScore; } public int getMathScore () { return MathScore; } public void setMathScore (int mathScore) { MathScore = mathScore; } @Override public int compareTo (Student s) { int STotal = s.ChineseScore + s.MathScore; int ThisTotal = this .ChineseScore + this .MathScore; int num = STotal - ThisTotal; int num2 = num == 0 ? this .name.compareTo(s.name) : num; return num2; } @Override public String toString () { return "姓名" + getName() + ", 语文成绩为" + getChineseScore() + ", 数学成绩为" + getMathScore() + ", 总分为" + (getChineseScore() + getMathScore()); } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Student student = (Student) o; return name != null ? name.equals(student.name) : student.name == null ; } @Override public int hashCode () { return name != null ? name.hashCode() : 0 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package 成绩排序;import java.util.HashSet;import java.util.TreeSet;public class ScoreSort { public static void main (String[] args) { Student s1 = new Student("Jiangeng Sun" , 112 ,150 ); Student s2 = new Student("Wong Zing" , 150 ,130 ); Student s3 = new Student("Weihan Li" , 150 ,150 ); Student s4 = new Student("Jitong Shi" , 130 ,150 ); Student s5 = new Student("Jitong Shi" , 130 ,150 ); Student s6 = new Student("Jitong Shi" , 129 ,140 ); TreeSet<Student> treeSet = new TreeSet<>(); HashSet<Student> hashSet = new HashSet<>(); hashSet.add(s1); hashSet.add(s2); hashSet.add(s3); hashSet.add(s4); hashSet.add(s5); hashSet.add(s6); for (Student s: hashSet){ System.out.println(s); treeSet.add(s); } System.out.println("-------------------" ); for (Student s: treeSet){ System.out.println(s); } } }
总结:为了输出好看,重写了toString
方法。为了过滤掉重复添加一个人元素,重写了hashCode
方法和equals()
方法,并且使用HashSet
过滤了一遍。
249. 不重复的随机数
需求:输出十个不同的1-20的随机数。
用的Math.random
写的,老师用的Random r
创建对象。核心思想不变。
也可以用TreeSet
生成,生成后会排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package 十个随机数;import java.util.HashSet;import java.util.Random;import java.util.Set;public class TenRandom { public static void main (String[] args) { boolean flag = true ; Set<Integer> set = new HashSet<Integer>(); while (flag) { int num = (int ) (Math.random() * 20 + 1 ); set.add(num); int size = set.size(); if (size == 10 ) { flag = false ; } } System.out.println(set); } }
250. 泛型概述和好处
这个就是泛型<>
。
泛型的好处:
把运行时的error
提前到了编译期间。
避免了强制类型转换。
251. 泛型类
用处:想用一个方法接收很多类型的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package Generic;public class Student <T > { private T t; public T getT () { return t; } public void setT (T t) { this .t = t; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package Generic;public class test { public static void main (String[] args) { Student<String> s = new Student<String>(); s.setT("名字" ); Student<Integer> s1 = new Student<Integer>(); s1.setT(21 ); System.out.println(s.getT()+"," +s1.getT()); } }
252. 泛型方法
可以在创建对象的时候不定义泛型,但是在调用实际方法的时候定义泛型。
1 2 3 4 5 6 7 8 9 10 package Generic;public class GenericStudent { public <T> void show (T t) { System.out.println(t); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package Generic;public class test { public static void main (String[] args) { GenericStudent genericStudent = new GenericStudent(); genericStudent.show("String类型" ); genericStudent.show(20 ); genericStudent.show(20.12 ); genericStudent.show(false ); } }
253. 泛型接口
定义格式:public interface Generic <T>{}
1 2 3 4 5 6 package 泛型接口;public interface Generic <T > { public void show (T t) ; }
1 2 3 4 5 6 7 8 9 package 泛型接口;public class GenericImplement <T > implements Generic <T > { @Override public void show (T t) { System.out.println(t); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package 泛型接口;public class test { public static void main (String[] args) { GenericImplement<String> GI = new GenericImplement<String>(); GI.show("林青霞" ); GenericImplement<Object> GI2 = new GenericImplement<Object>(); GI2.show("林青霞" ); GI2.show(30 ); } }
254. 类型通配符
类型的家族: Object
→ \rightarrow → Number
→ \rightarrow → Integer
<? extends Number>
决定了上限, <? super Number>
决定了下限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package 类型通配符;import java.util.ArrayList;import java.util.List;public class GenericDemo { public static void main (String[] args) { List<?> l = new ArrayList<Object>(); List<?> l2 = new ArrayList<Number>(); List<?> l3 = new ArrayList<Integer>(); List<? extends Number> l5 = new ArrayList<Number>(); List<? extends Number> l6 = new ArrayList<Integer>(); List<? super Number> l7 = new ArrayList<Object>(); List<? super Number> l8 = new ArrayList<Number>(); } }
255. 可变参数
方法中的参数的数量可变。本质上是把参数们分封装到一个数组中。
格式:public static int sun(int...a){};
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package 可变参数;public class ArgsDemo01 { public static void main (String[] args) { System.out.println(sum(10 ,20 )); System.out.println(sum(10 ,20 ,30 )); System.out.println(sum(10 ,20 ,30 ,40 )); System.out.println(sum(10 ,20 ,30 ,40 ,50 )); System.out.println(sum(10 )); System.out.println(sum()); } public static int sum (int ... a) { int sum = 0 ; for (int num : a) { sum += num; } return sum; } }
注意:一个方法如果有多个参数(单一的参数和可变参数并存),可变参数要放到后面,用逗号隔开。
256. 可变参数的使用
Arrays
工具类中有一个静态方法: asList(T... a )
: 返回由指定数组支持的固定大小的列表。
List
接口中有一个静态方法:of(E... elements)
:返回包含任意数量元素的不可变列表。
Set
接口中有一个静态方法:of(E... elements)
:返回一个包含任意数量元素的不可变集合。
注意:
正常用list
集合的话是创建list
对象(使用ArrayList
),然后add()
。使用asList(可变参数)
生成的列表,无法增删 !但是可以修改。
通过List.of
创建的列表,无法增删 和修改 。
Set
在赋值时元素不能重复,不能增删操作。没有修改操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package 可变参数的使用;import java.util.Arrays;import java.util.List;import java.util.Set;public class ArgsDemo { public static void main (String[] args) { List<String> list = Arrays.asList("hello" ,"world" ,"java" ); list.set(0 ,"hi" ); System.out.println(list); List<String>list2 = List.of("hello" ,"world" ,"java" ,"java" ); Set<String> set = Set.of("hello" ,"world" ,"java" ); } }