这里写目录标题
迭代器
上接day13
迭代:即Collection集合元素的通⽤获取⽅式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。⼀直把集合中的所有元素全部取出。这种取出⽅式专业术语称为迭代
- Iterable -> 可迭代的, iterator() -> 获得迭代器
- 获得迭代器时, 游标指向集合中第一个元素之前
- 遍历删除只能使用迭代器
public E next() :返回迭代的下⼀个元素。
public boolean hasNext() :如果仍有元素可以迭代,则返回 true。
迭代删除
- 不能在迭代器内部使用集合自己的remove方法,如集合.remove(迭代出的元素),会报异常:ConcurrentModificationException安全隐患
- 用 iterator.remove() 来替代
- remove(): 删除当前游标所在位置的元素,不会改变游标位置
Collection<String> col = new ArrayList<>();
col.add("鲁智深");
col.add("西门庆");
col.add("潘金莲");
col.add("武大郎");
col.add("武松");
Iterator<String> it = col.iterator();
while (it.hasNext()) {
// 迭代访问
String s = it.next();
// 打印对象
System.out.println(s);
// 将s对象删除
// col.remove(s);报异常
it.remove();
}
迭代器的简化
不用获得迭代器方法
简化 -> 增强for循环 forEach
for(每一次迭代出来的元素临时变量 : 要迭代的集合/数组) {
例如:
for(String s : col) {
System.out.println(s);
}
forEach可以遍历集合、数组,不能迭代移除
Collection<String> col = new ArrayList<>();
col.add("鲁智深");
col.add("西门庆");
col.add("潘金莲");
col.add("武大郎");
col.add("武松");
// : 右边 -> 要迭代的集合/数组
// : 左边 -> 每一次迭代取出的那个元素
// 等同于迭代器中的 String s = it.next()
for (String s : col) {
System.out.println(s);
}
System.out.println("-------------");
//遍历数组
int[] arr = {5, 12, 7, 3, 1};
for (int a : arr) {
System.out.println(a);
}
collection补充
toArray()
Object[] toArray():无参,返回值类型永远都是Object[],和泛型无关
T[] toArray(T[]): 参数->一个具体类型的数组, 作用只是为了提供类型
Collection<String> col = new ArrayList();
col.add("hello");
col.add("hi");
/*
toArray方法参数: 具体类型的数组, 数组长度无所谓
只是为了提供类型
返回值的数组类型, 取决于参数的数组类型
返回值的数组长度, 取决于集合的长度
*/
String[] ss = col.toArray(new String[0]);
for (String s : ss) {
System.out.println(s.length());
}
remove(Object o)
原理: 遍历集合, 默认将每一个元素.equals(o),判断对象是否一致
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
Collection<Student> col = new ArrayList<>();
Student s1 = new Student("张老三", 34);
Student s2 = new Student("李老六", 43);
col.add(s1);
col.add(s2);
System.out.println(col);
Student s3 = new Student("张老三", 34);
col.remove(s3); // 内部调用equals方法判断对象是否一致
System.out.println(col);
//[Student{name='张老三', age=34}, Student{name='李老六', age=43}]
//[Student{name='李老六', age=43}]
contains(Object o)一致
Arrays和Collections
Arrays
数组相关工具类
toString() -> 打印数组内容
sort(arr) -> 数组排序
copyOf() -> 数组复制
asList(arr)
asList(arr) -> List 将数组转换成集合
-> 本质上还是数组, 数组长度不可变
String[] ss = {"张三丰", "张无忌", "谢逊"};
// 将数组转换为 List 有序列表
List<String> list = Arrays.asList(ss);
System.out.println(list);
// list真正的类型是Arrays的内部类,不是我们真正的ArrayList
// 不能使用增\删的相关方法
/*list.add("赵敏");*/
/*System.out.println(list);*/
// 让list 变成一个真正的ArrayList
List<String> list1 = new ArrayList<>(list);
list1.add("赵敏");
System.out.println(list1);
Collections
集合相关工具类
sort(List)
sort(List) -> 给List排序, 只能传List,所有元素必须是可比较的
List<Integer> li = new ArrayList<>();
li.add(9);
li.add(3);
li.add(2);
li.add(7);
li.add(5);
System.out.println("排序之前: " + li);
Collections.sort(li);
System.out.println("排序之后: " + li);
Comparable
java.lang.Comparable -> 接口, 可比较的
int compareTo(T t)
public class Student implements Comparable<Student>{
private String name;
private Integer age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
// 按照年龄排序
return this.age - o.age;
// 让方法返回值<0, o.age < this.age
// return o.age - this.age;
// 按照姓名的字典顺序排序
// return this.name.compareTo(o.name);
}
public static void main(String[] args) {
List<Student> lstu = new ArrayList<>();
lstu.add(new Student("lucy", 23));
lstu.add(new Student("jack", 25));
lstu.add(new Student("tom", 18));
lstu.add(new Student("zhangsan", 8));
System.out.println("排序之前: " + lstu);
// 使用自定义比较器进行排序
Collections.sort(lstu);
System.out.println("排序之后: " + lstu);
//排序之前: [Student{name='lucy', age=23}, Student{name='jack', age=25}, Student{name='tom', age=18}, Student{name='zhangsan', age=8}]
//排序之后: [Student{name='zhangsan', age=8}, Student{name='tom', age=18}, Student{name='lucy', age=23}, Student{name='jack', age=25}]
自定义比较器Comparator
结论 :
- 可以不使用比较器, 要求元素的类必须是可比较的Comparable
- sort: 可以使用自定义比较器Comparator, 元素的类可以没有任何要求
- Comparator: 可以忽略掉本身的比较规则 - compareTo来自定义比较规则
意义:多种比较规则同时存在,例如先比较名字,后比较年龄
public class Student{
public class MyComparator implements Comparator<Student>{
/**
* 比较 o1 和 o2
* @return >0 o1 > o2
* =0 o1 = o2
* <0 o1 < o2
*/
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
List<Student> lstu = new ArrayList<>();
lstu.add(new Student("lucy", 23));
lstu.add(new Student("jack", 25));
lstu.add(new Student("tom", 18));
lstu.add(new Student("zhangsan", 8));
System.out.println("排序之前: " + lstu);
// 使用自定义比较器进行排序
Collections.sort(lstu, new MyComparator());
System.out.println("排序之后: " + lstu);
简化版
List<String> ls = new ArrayList<>();
ls.add("lucy");
ls.add("zhangsan");
ls.add("tom");
ls.add("lisi");
ls.add("jack");
System.out.println("排序之前: " + ls);
Collections.sort(ls);
System.out.println("字典排序之后: " + ls);
// 按照字符串长度来排序, 长的在前面, 短的在后面
Collections.sort(ls, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.length() - o1.length();
}
});
System.out.println("长短排序之后: " + ls);
有序二叉树
不允许重复
特点: 左节点 < 父节点 < 右节点
中序遍历: 左节点, 中间节点[根节点], 右节点
遍历结果: 升序
public class SortedTree{
private class Node{
private int data;
private Node left;
private Node right;
private Node(int data) {
this.data = data;
}
}
private Node root; // 根节点, 最开始为null
// 给自己使用
private void travelNode(Node node) {
if (node.left != null) {
travelNode(node.left);
}
System.out.println(node.data);
if (node.right != null) {
travelNode(node.right);
}
}
// 给外部提供的方法
public void travel() {
travelNode(root);
}
private void addToNode(Node node, int data) {}
public void add(int a) {
// 先判断a是不是第一个元素
if (root == null) {
root = new Node(a);
return;
}
Node node = root; // 记录每一次的当前节点
Node parentNode; // 记录每一次node的父节点
// 不是第一个元素
while(true) {
parentNode = node;
if (node.data > a) {
// a向左边节点继续比较
node = node.left;
if (node == null) {
parentNode.left = new Node(a);
return;
}
} else if (node.data < a) {
// a向右边节点继续比较
node = node.right;
if (node == null) {
parentNode.right = new Node(a);
return;
}
}
}
public static void main(String[] args){
SortedTree tree = new SortedTree();
tree.add(53);
tree.add(23);
tree.add(10);
tree.add(45);
tree.travel();
JavaBean规范
JavaBean规范: 实体类的书写规范
1.成员变量私有化, 提供get/set方法
2.定义无参构造方法
3.重写toString,equals 和 hashCode
4.基本数据类型建议使用包装类
5.实现 Serializable 接口(可序列化的)
6.不能使用final修饰(不能被继承,就不能使用cglib动态代理)