迭代器, 数组和集合的转换, Comparable和Comparator, 二叉树
1.迭代器
1.迭代器中使用迭代, 然后直接使用 集合.remove(迭代出的元素)
异常: ConcurrentModificationException
安全隐患
解决: 不能在迭代器内部使用集合自己的remove方法
用 iterator.remove() 来替代
remove(): 删除当前游标所在位置的元素
不会改变游标位置
2.迭代器的简化 -> 增强for循环 forEach
for(每一次迭代出来的元素临时变量 : 要迭代的集合/数组) {
}
例如:
public class forEach {
public static void main(String[] args) {
int[] a = new int[]{5, 4, 2, 3, 1};
//iterator的简化版 遍历常用
for(int i: a){
System.out.println(i);
}
}
}
注意: forEach只能遍历元素使用, 不能迭代移除
3.List: 特点 -> 有序的[有下标], 允许重复元素
有序: 添加顺序就是访问顺序
排序: 由小到大, 由大到小
List的遍历/迭代:
可以用Iterator
forEach
for
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class removeFunction {
public static void main(String[] args) {
Collection<String> col = new ArrayList<>();
col.add("怪物猎人");
col.add("赛博朋克2077");
col.add("看门狗");
col.add("刺客信条");
col.add("黎明杀机");
//迭代器简化
/* for(String c: col){
System.out.println(c);
}*/
Iterator<String> it = col.iterator();
while (it.hasNext()){
System.out.println(it.next());
it.remove();//迭代器remove是删除游标下的元素,所以一定是在next方法之后调用,开始的游标位置在集合之外
}
for(String c: col){
System.out.println(c);
}
System.out.println(col.isEmpty());//元素全部删除
}
}
2.数组和集合的转换
1.Collection: toArray
Object[] toArray():无参,返回值类型永远都是Object[],和泛型无关
T[] toArray(T[]):参数->一个具体类型的数组, 作用只是为了提供类型
2.Collection: remove
remove(Object o)
原理: 遍历集合, 将每一个元素.equals(o)
contains(Object o)
3.java.util.Arrays: 数组相关工具类
toString() -> 打印数组内容
sort(arr) -> 数组排序
copyOf() -> 数组复制
asList(arr) -> List 将数组转换成集合
-> 本质上还是数组, 数组长度不可变
代码体现:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//将数组转化为List(有序列表)类
public class asList {
public static void main(String[] args) {
String[] s = {"lucy", "hzt", "mike", "naruto"};
List<String> list = Arrays.asList(s);
//从数组转化成列表所用的是ArrayList的内部类 即不是真正的ArrayList类 其中不包含任何修改列表size的方法
//例如add,remove,
// list.add("k");
// list.sort();
//如果想要改变size需要把其转换成真正的ArrayList类型
ArrayList<String> trueArrayList = new ArrayList<>(list);
trueArrayList.add("k");
System.out.println(trueArrayList);
}
}
3. Comparable和Comparator
.java.util.Collections: 集合相关的工具类
sort(List) -> 给List排序, 所有元素必须是可比较的
java.lang.Comparable -> 接口, 可比较的
int compareTo(T t)
Collections.sort(list)
list.sort(null) null -> Comparator
1.列表list -> 数组a
2.Arrays.sort(a, (Comparator) c); c->null
if (c == null) {
sort(a); -> ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
} else {
c.compare(pivot, a[mid])
}
Collections.sort(list, new Comparator)
Comparator <? super T>
结论 -
sort: 可以使用自定义比较器Comparator, 元素的类可以没有任何要求
可以不使用比较器, 要求元素的类必须是可比较的Comparable
Comparator: 可以忽略掉本身的比较规则 - compareTo
自定义比较规则
创建student类实现Comparable接口:
import java.util.Objects;
public class Student implements Comparable<Student> {
private String name;
private int 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;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//col默认的equals比较的是对象的地址,因为new出的对象地址肯定不同所以无法删除 故需重写类的equals方法
@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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/* this的属性与参数对象的可比较属性相比较
this.flied > o.flied* 返回 >0
this.flied = o.flied* 返回 0
this.flied < o.flied* 返回 <0*/
/*//比较age属性 compareTo方法返回的是int类型
@Override
public int compareTo(Student o) {
return this.age - o.age;
}*/
//比较name属性
@Override
public int compareTo(Student o) {
return this.name.compareTo(o.name);
}
}
集合转换为数组,Comparator的方法重写
import java.util.*;
public class ToArray {
public static void main(String[] args) {
List<Student> col = new ArrayList<>();
col.add(new Student("lucy",17));
col.add(new Student("philips",18));
col.add(new Student("franklin",15));
col.add(new Student("mike",14));
//将集合转换为数组
Object[] s1 = col.toArray();//返回值必须为Object数
System.out.println(Arrays.toString(s1));
Student s = new Student("lucy", 17);
col.remove(s);//会调用对象的equals方法 比较集合中的元素与参数列表中的元素 比较方式看equals方法 只删除比较相同的第一元素
Object[] s2 = col.toArray(new Student[0]);//参数为返回值的数组类型,数组长度无影响
System.out.println(Arrays.toString(s2));
//Collections的sort方法, 比较的对象必须实现Comparable接口
//sort方法中调用的compareTo方法对应可比较类型的比较方式固定, 无法修改
Collections.sort(col);
System.out.println("按名字排序后:" + col);
//创建比较器的实现类对象
MyComparator comparator = new MyComparator();
//使用对象的compare方法
int a = comparator.compare(col.get(0), col.get(1));
System.out.println(a);
//当多种比较规则同时存在为了自定义多种比较方法 需要使用比较器
// 在sort方法中调用比较器
//使用匿名内部类自定义比较器方法
Collections.sort(col, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().length() - o2.getName().length();//升序
}
});
System.out.println("按name属性长度升序排序:" + col);
Collections.sort(col, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getName().length() - o1.getName().length();//降序
// 例如返回值为负数就认为是o1小就将o1放在前面,但是实时上是o2小于o1 就相当于把比较大的o1放在前面就等同于降序
}
});
System.out.println("按name属性长度降序排序:" + col);
}
}
4.有序二叉树
有序二叉树: - 不允许重复
特点: 左节点 < 父节点 < 右节点
中序遍历: 左节点, 中间节点[根节点], 右节点
遍历结果: 升序
代码实现:
public class BinaryTree {
//定义节点
private class Node{
int data;//节点存储的数据
private Node left;//指向左边叶子节点的指针
private Node right;//指向右边叶子节点的指针
//节点构造方法
public Node(){}
public Node(int data){
this.data = data;
}
}
//初始化根节点
private Node root;
//添加节点方法
public void add(int data){
//判断根节点是否为空
if(root == null){
root = new Node(data);//为空就将新增节点定为根节点
return;//方法结束返回
}
//定义父节点(每次比较时比较的节点对象)
Node parentNode = root;//初始化为根节点
//不停的寻找下一个节点知道将新增节点加入二叉树
while (true){
//比较新增节点与父节点大小
if(parentNode.data > data){
//如果新增节点比父母节点值小就找左边的下一个节点
// 如果父母节点左边的下一个节点值为空就将父节点的left属性指向新增节点
if(parentNode.left == null){
parentNode.left = new Node(data);
return;//赋值完毕 方法结束
}
//如果父母节点的左边下一个节点值不为空就将父母节点赋值为左边的下一个节点
parentNode = parentNode.left;
}else if(parentNode.data < data){
//如果新增节点比父母节点值大就找右边的下一个节点
// 如果父母节点右边的下一个节点值为空就将父节点的right属性指向新增节点
if(parentNode.right == null){
parentNode.right = new Node(data);
return;//赋值完毕 方法结束
}
//如果父母节点的右边的下一个节点值不为空就将父母节点赋值为右边的下一个节点
parentNode = parentNode.right;
}
}
}
//遍历
private void nodeTravel(Node node){
//遍历左节点
if(node.left != null){
nodeTravel(node.left);//从下一个左节点开始遍历
}
//如果node.left为空则输出node值
System.out.println(node.data);
//左节点遍历完,中节点输出,从右节点开始遍历
if(node.right != null) {
nodeTravel(node.right);
}
}
//外部用遍历方法
public void travel(){
nodeTravel(root);
}
}
public class Test {
public static void main(String[] args) {
BinaryTree tree = new BinaryTree();
//添加
tree.add(1);
tree.add(2);
tree.add(7);
tree.add(9);
tree.add(6);
tree.add(4);
//中序遍历 遍历后结果为升序
tree.travel();
}
}