从零开始的Java知识(上)

拼图小游戏(Day16)

JFrame 窗体

		JFrame jFrame = new JFrame();
		// 设置窗体宽高
		jFrame.setSize(400, 500);
		// 设置窗体标题
		jFrame.setTitle("测试弹窗");
		// 设置窗体置顶
		jFrame.setAlwaysOnTop(true);
		// 设置窗体居中
		jFrame.setLocationRelativeTo(null);
		// 设置窗体关闭模式
		jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		// 取消窗体默认居中,如此设置坐标生效
		jFrame.setLayout(null);
		// 窗体可见
		jFrame.setVisible(true);

菜单

		JFrame jFrame = new JFrame();
		// 菜单行
		JMenuBar jMenuBar = new JMenuBar();
		// 菜单具体栏
		JMenu jMenu = new JMenu("功能");
		// 菜单具体栏下拉框
		JMenuItem jMenuItem1 = new JMenuItem("重新开始");
		JMenuItem jMenuItem2 = new JMenuItem("退出");

		jMenu.add(jMenuItem1);
		jMenu.add(jMenuItem2);
		jMenuBar.add(jMenu);

		jFrame.setJMenuBar(jMenuBar);

在这里插入图片描述

窗体内容

用于短文本字符串或图像或两者的显示区域。

	// 填充一个图片
	public static void addImage(JFrame jFrame) {
		// 创建图标对象
		ImageIcon imageIcon = new ImageIcon("C:/workspace/lv_learn/image/1.png");
		// jLabel填充图标
		JLabel jLabel = new JLabel(imageIcon);
		// jLabel设置坐标和宽高
		jLabel.setBounds(0, 0, 105, 105);
		// 窗体填充jLabel
		jFrame.getContentPane().add(jLabel);
	}
	
	// 填充一个动作监听按钮1
	public static void addActionButton1(JFrame jFrame) {
		JButton jButton = new JButton("动作监听1");
		jButton.setBounds(105, 0, 105, 30);
		// 设置监听方式1: 使用匿名内部类
		jButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("动作监听捕获1");
			}
		});
		jFrame.getContentPane().add(jButton);
	}
	
	// 填充一个鼠标监听按钮1
	public static void addMouseButton1(JFrame jFrame) {
		JButton jButton = new JButton("鼠标监听1");
		jButton.setBounds(0, 105, 105, 30);
		jButton.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
				System.out.println("鼠标释放");
			}

			@Override
			public void mousePressed(MouseEvent e) {
				System.out.println("鼠标按下");
			}

			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("鼠标划出");
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("鼠标划入");
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("鼠标点击");
			}
		});
		jFrame.add(jButton);
	}

	// 填充一个键盘监听按钮1
	public static void addKeyButton1(JFrame jFrame) {
		JButton jButton = new JButton("键盘监听1");
		jButton.setBounds(0, 105 * 2, 105, 30);
		jButton.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
				System.out.println("键盘按下之后");
			}

			@Override
			public void keyReleased(KeyEvent e) {
				System.out.println("键盘释放");
				int keyCode = e.getKeyCode();
				switch (keyCode) {
				case 65:
					System.out.println("键盘释放A");
					break;
				case 66:
					System.out.println("键盘释放B");
					break;
				default:
					System.out.println("键盘释放未知");
					break;
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("键盘按下");
			}
		});
		jFrame.add(jButton);
	}

窗体内容美化(Day17)

  1. 拼图图片位置整体偏移至窗体中间
  2. 加入背景图,背景图的加入位置放在拼图图片后面,原因是先加入的图片会再后加入图片的上方。
  3. 为拼图图片设置边框
  4. 将拼图图片的路径由绝对路径修改为相对路径(模块名/…)

移动图片

  1. 整个窗体设置键盘监听事件, jFrame.setKeyListener…
  2. 记录空白拼图下标 x,y
  3. 键盘松开逻辑判断设置,注意空白拼图的左移,相当于图片的右移(逻辑比较绕)
  4. 键盘松开逻辑判断后,重新设置一次拼图 initImage
  5. 重新设置需要窗体内容部分(jFrame.getContentPane().removeAll()),删除当前的拼图部分,最后重新repaint一下(jFrame.getContentPane().repaint())

弹出提示图

  1. 窗体对象设置键盘监听事件, jFrame.setKeyListener…
  2. 键盘按下显示提示图
  3. 键盘松开还原拼图

其他(略)

常用API(Day18)

Math

package com.itheima.day18;

public class MathTest {

	public static void main(String[] args) {
		// abs 取值范围最小值不能取到绝对值
		System.out.println(Math.abs(-11)); // 11
		System.out.println(Math.abs(11)); // 11
		System.out.println(Math.abs(-2147483648)); // -2147483648
		System.out.println(Math.abs(-2147483647)); // 2147483647
		// ceil
		// floor
		// round
		System.out.println(Math.ceil(11.2)); // 12.0
		System.out.println(Math.ceil(-11.2));// -11.0
		System.out.println(Math.floor(11.2)); // 11.0
		System.out.println(Math.floor(-11.2));// -12.0
		System.out.println(Math.round(11.2));// 11.0
		System.out.println(Math.round(11.5));// 12.0
		System.out.println(Math.round(-11.2));// -11.0
		System.out.println(Math.round(-11.6));// -12.0
		// pow
		// sqrt
		// cbrt
		System.out.println(Math.pow(2, 3)); // 8.0
		System.out.println(Math.sqrt(16)); // 4.0
		System.out.println(Math.cbrt(8)); // 2.0
		// max
		// min
		System.out.println(Math.max(3, 2)); // 3
		System.out.println(Math.min(3, 2)); // 2
		// random
		for (int i = 0; i < 100; i++) {
			System.out.println(Math.ceil(Math.random() * 100)); // 1.0~100.0
		}
	}
}

System

package com.itheima.demo;

public class SystemTest {
    public static void main(String[] args) {
        // exit 终止java虚拟机
        // 0:正常结束 非0:异常结束
        //System.exit(0);

        // currentTimeMillis(); 记录当前事件距离时间原点的毫秒差值
        // 时间原点:1970.01.01 00:00:00
        // 北京东八区时间原点:1970.01.01 08:00:00
        long start = System.currentTimeMillis();
        System.out.println(start);

        // arraycopy(数组源头,数组源头开始下标,拷贝数组,数组开始下标,拷贝长度)
        // 注意1:如果都是基本数据类型,则数据类型必须保持一致,否则报错
        try {
            int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
            double[] arr2 = new double[10];
            System.arraycopy(arr1, 0, arr2, 0, arr1.length);
            for (int i = 0; i < arr2.length; i++) {
                System.out.println(arr2[i]);
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        // 注意2:如果都是引用数据类型,子类对象可以拷贝给父类对象
        try {
            Student[] arr1 = {new Student("张三", 18), new Student("李四", 19), new Student("王五", 20)};
            Person[] arr2 = new Person[10];
            System.arraycopy(arr1, 0, arr2, 3, arr1.length);
            for (int i = 0; i < arr2.length; i++) {
                System.out.println(arr2[i]);
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        // 注意3:如果超出拷贝数组长度,报错
        try {
            Student[] arr1 = {new Student("张三", 18), new Student("李四", 19), new Student("王五", 20)};
            Person[] arr2 = new Person[3];
            System.arraycopy(arr1, 0, arr2, 1, 3);
            for (int i = 0; i < arr2.length; i++) {
                System.out.println(arr2[i]);
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}

class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person {
    public Student(String name, int age) {
        super(name, age);
    }
}

Runtime

package com.itheima.demo;

import java.io.IOException;

public class RuntimeTest {
    public static void main(String[] args) throws IOException {
        // getRuntime() 获取当前程序运行环境
        Runtime runtime = Runtime.getRuntime();
        // exit 终止JVM
//        runtime.exit(0);
        // availableProcessors 返回JVM可用的处理器的数目
        System.out.println(runtime.availableProcessors());
        // 返回JVM最大使用的内存大小byte
        System.out.println(runtime.maxMemory() / 1024 / 1024);
        // 返回JVM已经获取的内存大小byte
        System.out.println(runtime.totalMemory() / 1024 / 1024);
        // 返回JVM未使用的内存大小byte
        System.out.println(runtime.freeMemory() / 1024 / 1024);
        // exec 执行cmd命令
        runtime.exec("notepad");
        // shutdown -s 默认一分钟后关机
        // shutdown -s -t 秒数
        // shutdown -a 终止关机
        // shutdown -r 关机重启

    }
}

Object和Objects

package com.itheima.demo;

public class ObjectTest {
    public static void main(String[] args) {
        Object object = new Object();
        System.out.println(object);
        // object.toString() 全类名+@+十六进制地址
        System.out.println(object.toString());

        //object.equals(..) 返回地址比较的结果
        System.out.println(object.equals("12"));

        String str = "123";
        StringBuilder stringBuilder = new StringBuilder("123");
        // String.equals(..) 先比较地址是否相同,如果相同return true
        // 否则比较是不是都是String类型的数据,如果不是return false
        // 如果是则比较字符是否一一对应
        System.out.println(str.equals(stringBuilder)); // false
        // StringBuilder没有重写equals方法,调用的是object方法
        System.out.println(stringBuilder.equals(str)); // false
    }
}

package com.itheima.demo;

import java.util.Objects;
import java.util.StringJoiner;

public class Object2Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        // clone() 类继承Cloneable接口后
        // 默认的克隆方式是浅克隆
        // 意思就是把栈中的值传给新的对象

        // 深克隆需要自定义方法,或者引用第三方工具类
        Teacher t1 = new Teacher("张三", 18, new String[]{"吃饭", "睡觉", "打豆豆"});
        Teacher t2 = (Teacher) t1.clone();
        t1.interests[0] = "学习";
        System.out.println(t1);
        System.out.println(t2);
        System.out.println(t1 == t2); // false
        System.out.println(t1.interests == t2.interests); // 深克隆 false 浅克隆 true
        System.out.println("===============================");
        //Objects
        // equals 进行了空判定,返回为false
        // isNull 是否为空
        // nonNull 是否不为空
        Teacher t3 = null;
        Teacher t4 = null;
        System.out.println(Objects.equals(t1, t2)); // false
        System.out.println(Objects.equals(t2, t3)); // false
        System.out.println(Objects.equals(t3, t4)); // false

        System.out.println(Objects.isNull(t1)); // false
        System.out.println(Objects.isNull(t3)); // true

        System.out.println(Objects.nonNull(t1)); // true
        System.out.println(Objects.nonNull(t3)); // false
    }
}

// 克隆必须实现Cloneable
class Teacher implements Cloneable {
    String name;
    int age;
    String[] interests;

    public Teacher(String name, int age, String[] interests) {
        this.name = name;
        this.age = age;
        this.interests = interests;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // return super.clone();
        Teacher t2 = (Teacher) super.clone();
        String[] newStrs = new String[interests.length];
        System.arraycopy(interests, 0, newStrs, 0, interests.length);
        t2.interests = newStrs;
        return t2;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", interests=" + interestsStr() +
                '}';
    }

    private String interestsStr() {
        StringJoiner stringJoiner = new StringJoiner(",", "[", "]");
        for (int i = 0; i < interests.length; i++) {
            stringJoiner.add(interests[i]);
        }
        return stringJoiner.toString();
    }
}

BigInteger

package com.itheima.demo;

import java.math.BigInteger;
import java.util.Random;

public class BigIntegerTest {
    public static void main(String[] args) {
        // 1.new BigInteger(int,random) 随机0 ~ 2^4 - 1
        BigInteger bigInteger1 = new BigInteger(4, new Random());
        System.out.println(bigInteger1);
        // 2.new BigInteger(str) str转大整数
        BigInteger bigInteger2 = new BigInteger("100");
        System.out.println(bigInteger2);
        // 3.new BigInteger(str,int) 其他进制转十进制
        BigInteger bigInteger3 = new BigInteger("100", 2);
        System.out.println(bigInteger3);
        // 4.BigInteger.valueOf(long) long转大整数
        // valueOf(-16~16)是类的静态属性值赋予的
        // 超出long的最大值报错
        BigInteger bigInteger4 = BigInteger.valueOf(100l);
        System.out.println(bigInteger4);

        System.out.println("==============================");

        BigInteger b1 = BigInteger.valueOf(10);
        BigInteger b2 = BigInteger.valueOf(2);

        // 1.add
        BigInteger b3 = b1.add(b2);
        System.out.println(b3); // 12
        // 2.subtract
        BigInteger b4 = b1.subtract(b2);
        System.out.println(b4); // 8
        // 3.multiply
        BigInteger b5 = b1.multiply(b2);
        System.out.println(b5); // 20
        // 4.divide
        BigInteger b6 = b1.divide(b2);
        System.out.println(b6); //5
        // 5.divideAndRemainder
        BigInteger[] b7 = b1.divideAndRemainder(b2);
        System.out.println(b7[0] +" "+b7[1]); //5 0
        // 6.equals
        System.out.println(b1.equals(b2)); // false
        // 7.pow
        BigInteger b8 = b1.pow(2);
        System.out.println(b8); // 100
        // max/min
        BigInteger b9 = b1.max(b2);
        BigInteger b10 = b1.min(b2);
        System.out.println(b9 == b1); //true
        System.out.println(b9 == b2); //false
        System.out.println(b10 == b1); //false
        System.out.println(b10 == b2); //true
        // intValue
        int b11 = b1.intValue();
        System.out.println(b11); // 10
		
		// signum 代码正负号 或零
		// [] 从大到小存储划分32位的int数据[...,64~33,32~1]
		// 理论最大范围:int最大数的int范围的幂次方
    }
}

BigDecimal

package com.itheima.demo;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalTest {
    public static void main(String[] args) {
        // 1.浮点型的运算可能会因为小数位转换成二进制后过长,从而丢失了超出长度的二进制位的数据
        // 导致浮点数的运算之间也出现了误差
        // BigDecimal的出现解决了两个浮点数的两个问题
        // 一. 可以存储更大的浮点数数据
        // 二. 可以进行浮点数的精确运算

        // 2.实例化BigDecimal的方式
        // 一. 如果数据过大 new BigDecimal(str)
        // 二. 如果是小的浮点数 BigDecimal.valueOf(double)
        // 三. 如果是0~10包括10的整数 BigDecimal.valueOf(long) 节省内存空间
        BigDecimal bd1 = new BigDecimal(0.226);
        BigDecimal bd2 = new BigDecimal("0.226");
        BigDecimal bd3 = BigDecimal.valueOf(0.226);
        BigDecimal bd4 = BigDecimal.valueOf(10);
        BigDecimal bd5 = BigDecimal.valueOf(10);
        BigDecimal bd6 = BigDecimal.valueOf(11);
        BigDecimal bd7 = BigDecimal.valueOf(11);

        System.out.println(bd1); // 有误差 0.2260000000000000064392935428259079344570636749267578125
        System.out.println(bd2); // 0.226
        System.out.println(bd3); // 0.226
        System.out.println(bd4 == bd5); // true
        System.out.println(bd6 == bd7); // false

        // 3.常用的运算方法
        BigDecimal bd8 = BigDecimal.valueOf(10);
        BigDecimal bd9 = BigDecimal.valueOf(4);
        BigDecimal bd10 = BigDecimal.valueOf(3);

        // 加
        System.out.println(bd8.add(bd9)); // 14
        // 减
        System.out.println(bd8.subtract(bd9)); // 6
        // 乘
        System.out.println(bd8.multiply(bd9)); // 40
        // 除
        System.out.println(bd8.divide(bd9)); // 2.5 除尽
        try {
            System.out.println(bd8.divide(bd10)); // 除不尽报异常
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        // 四舍五入保留两位小数
        System.out.println(bd8.divide(bd10, 2, RoundingMode.HALF_UP)); // 3.33

        // 4.底层存储是将double->byte[] 报错每一位的ASCII码,包括负号
        BigDecimal bigDecimal1 = BigDecimal.valueOf(-3.33);
        // -3.33 -> [45,51,46,51,51]
        BigDecimal bigDecimal2 = BigDecimal.valueOf(3.33);
        // 3.33 -> [51,46,51,51]
    }
}

Arrays

package com.itheima.demo;

import java.util.Arrays;
import java.util.Comparator;

public class ArraysTest {
	public static void main(String[] args) {
		int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
		// 1.Arrays.toString(数组): 数组转换成数组字符串
		System.out.println(Arrays.toString(nums));
		// 2.Arrays.copyOf(旧数组,新数组长度);
		System.out.println("---------------------------------------------------");
		System.out.println(Arrays.toString(Arrays.copyOf(nums, nums.length - 1))); // 部分拷贝
		System.out.println(Arrays.toString(Arrays.copyOf(nums, nums.length)));
		System.out.println(Arrays.toString(Arrays.copyOf(nums, nums.length + 1))); // 超出进行赋默认值
		// 3.Arrays.copyOfRange(旧数组,开始下标,结束下标) 包左不包右
		System.out.println("---------------------------------------------------");
		System.out.println(Arrays.toString(Arrays.copyOfRange(nums, 0, 2)));
		System.out.println(Arrays.toString(Arrays.copyOfRange(nums, 2, nums.length)));
		// 4.Arrays.binarySearch(数组,查询值) 数组必须是正有序数据
		System.out.println("---------------------------------------------------");
		System.out.println(Arrays.binarySearch(nums, 1)); // 0
		System.out.println(Arrays.binarySearch(nums, 11));// -11
		System.out.println(Arrays.binarySearch(nums, 0)); // -1
		// 5.Arrays.fill(值) 填充覆盖原始数据
		System.out.println("---------------------------------------------------");
		Arrays.fill(nums, 100);
		System.out.println(Arrays.toString(nums));
		// 6.Arrays.sort(数组)
		System.out.println("---------------------------------------------------");
		Integer[] nums1 = { 1, 7, 8, 9, 10, 2, 3, 4, 5, 6 };
//		Arrays.sort(nums1);
//		System.out.println(Arrays.toString(nums1)); // 正序
		// 插值排序 + 二分查找
		Arrays.sort(nums1, new Comparator<Integer>() {
			/**
			 * o1 插入值 o2 二分查找值
			 */
			@Override
			public int compare(Integer o1, Integer o2) {
				System.out.println("o1:" + o1 + ",o2:" + o2);
				return o2 - o1;
			}
		});
		System.out.println(Arrays.toString(nums1));// -11
	}
}

正则表达式(Day19)

1. 字符数据的校验

更详细的正则相关字符说明查询Pattern API
链接:https://doc.qzxdp.cn/jdk/17/zh/api/java.base/java/util/regex/Pattern.html

package com.itheima.demo;

public class PatternTest {
    public static void main(String[] args) {
        // 正则表达式主要是为了快速校验而出现的数据
        // 1.字符类
        System.out.println("a".matches("[abc]"));  //true
        System.out.println("a".matches("[^123]")); //非 true
        System.out.println("a".matches("[a-bd-f]"));// 和 true
        System.out.println("a".matches("[a-c&&c-e]")); // 交集 false
        System.out.println("c".matches("[a-c&&c-e]")); // true
        System.out.println("c".matches("[a-c&&[^c-e]]")); // false
        System.out.println("=====================================");
        // 2.预定义字符类
        System.out.println("a".matches("\\d")); //[0-9] false
        System.out.println("a".matches("\\D")); //[^0-9] true
        System.out.println("a".matches("\\w")); //[a-zA-Z0-9] true
        System.out.println("a".matches("\\W")); //[^a-zA-Z0-9_] //false
        System.out.println("a".matches(".")); // 任意字符(\n除外) true
        System.out.println("a".matches("\\."));// . false
        System.out.println("=====================================");
        // 3.所有格量词类
        System.out.println("aa".matches("\\w?")); //0或1 false
        System.out.println("aa".matches("\\w+")); //1或n true
        System.out.println("aa".matches("\\w*")); //0或n true
        System.out.println("aa".matches("\\w{2}")); // 2 true
        System.out.println("aaa".matches("\\w{2,}")); // >=2 true
        System.out.println("aaa".matches("\\w{2,3}")); // >=2 <=3 true
        // 4. | 并集
        // 5. (?i) 忽略大小写
        // 6. () 分组
    }
}

2.文本数据的爬取

package com.itheima.demo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternTest02 {
    public static void main(String[] args) {
        String text = "JDK是java开发工具,最常用的JDK有JDK7,JDK8,JDK17";
        // 1.定义正则表达式对象
        Pattern pattern = Pattern.compile("JDK\\d{0,2}");
        // 2.生成指定文本的匹配器
        Matcher matcher = pattern.matcher(text);
        // 3.遍历
        // 3.1 matcher.find() 记录是否匹配成功,匹配成功返回true,内部记录开始的索引,和结束索引+1
        while(matcher.find()){
            // 3.2 matcher.group() 记录匹配成功的数据
            System.out.println(matcher.group());
        }
    }
}

3.文本数据爬取拓展

package com.itheima.demo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternTest03 {
    public static void main(String[] args) {
        // ?= 爬取匹配数据且只打印指定部分数据
        // ?: 爬取匹配数据打印匹配数据
        // ?! 爬取不满足匹配设置的数据, 且只打印指定部分数据
        String text = "JDK是JAVA开发工具,最常用的JDK版本有JDK7,JDK8,JDK17;JDK21也即将成为稳定的版本";
        Pattern pattern1 = Pattern.compile("JDK(?=\\d{0,2})");
        Matcher matcher1 = pattern1.matcher(text);
        while (matcher1.find()) {
            System.out.print(matcher1.group() + " ");
        }
        // result: JDK JDK JDK JDK JDK JDK
        System.out.println("");

        Pattern pattern2 = Pattern.compile("JDK(?:\\d{0,2})");
        Matcher matcher2 = pattern2.matcher(text);
        while (matcher2.find()) {
            System.out.print(matcher2.group() + " ");
        }
        // result: JDK JDK JDK7 JDK8 JDK17 JDK21
        System.out.println("");
        Pattern pattern3 = Pattern.compile("JDK(?!\\d{2})");
        Matcher matcher3 = pattern3.matcher(text);
        while (matcher3.find()) {
            System.out.print(matcher3.group() + " ");
        }
        // result: JDK JDK JDK JDK

        // 正则匹配器默认是贪婪爬取,即尽可能匹配的更长
        // 在+ * 等数量词后面加上问号(?) 变成非贪婪爬取,即尽可能匹配的更短
        System.out.println("");
        Pattern pattern4 = Pattern.compile("JDK\\d+");
        Matcher matcher4 = pattern4.matcher(text);
        while(matcher4.find()){
            System.out.print(matcher4.group()+" ");
        }
        // JDK JDK JDK7 JDK8 JDK17 JDK21

        System.out.println("");
        Pattern pattern5 = Pattern.compile("JDK\\d+?");
        Matcher matcher5 = pattern5.matcher(text);
        while(matcher5.find()){
            System.out.print(matcher5.group()+" ");
        }
        // JDK JDK JDK7 JDK8 JDK1 JDK2

        // 字符串的相关方法的正则应用,需要以API的方法为准
        // 例子:
        // matches(String regex)
        // replaceAll(String regex, String replacement)
        // replaceFirst(String regex, String replacement)
        // split(String regex)
        // split(String regex, int limit)
        System.out.println("");

        String text1 = "吕懿洋afljsldkjflkj1243李桂祥asjdflkdjsflkj李敏";
        // && 后面追加的也要用[] 括起来
        System.out.println(text1.replaceAll("[\\w&&[^_]]+","vs")); // 吕懿洋vs李桂祥vs李敏
        String[] array = text1.split("[\\w&&[^_]]+");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]+" "); // 吕懿洋 李桂祥 李敏
        }
    }
}

4.捕获分组和非捕获分组

package com.itheima.demo;

public class PatternTest04 {
    public static void main(String[] args) {
        // 1.分组 ()
        // 以左括号为准记录组数,从1开始
        // 正则表达式默认是捕获分组 \\1代表捕获第一组的值
        System.out.println("a123a".matches("(.).+\\1")); // true
        System.out.println("b456b".matches("(.).+\\1")); // true
        System.out.println("17891".matches("(.).+\\1")); // true
        System.out.println("&abc&".matches("(.).+\\1")); // true
        System.out.println("===================================");
        System.out.println("abc123abc".matches("(.+).+\\1")); // true
        System.out.println("b456b".matches("(.+).+\\1")); // true
        System.out.println("123789123".matches("(.+).+\\1")); // true
        System.out.println("&!@abc&!@".matches("(.+).+\\1")); // true
        System.out.println("===================================");
        System.out.println("aaa123aaa".matches("((.)\\2*).+\\1")); // true
        System.out.println("bbb456bbb".matches("((.)\\2*).+\\1")); // true
        System.out.println("111789111".matches("((.)\\2*).+\\1")); // true
        System.out.println("&&abc&&".matches("((.)\\2*).+\\1")); // true
        System.out.println("ababcab".matches("((.)\\2*).+\\1")); // false

        System.out.println("===================================");
        String str = "我要学学学学学学编编编编编编编程程程程程程程程程程程";
        // $1 约等于 \\1
        System.out.println(str.replaceAll("(.)\\1+","$1")); // 我要学编程

        //2. ?: ?! ?= 都是非捕获分组,是没有需要的
        System.out.println(str.replaceAll("(.)(?:\\1)\\1*","$1")); // 我要学编程
    }
}

日期类(Day20)

JDK7版本相关

Date类
package com.glad.flowable;

import java.util.Date;
import java.util.Random;

public class DateTest01 {

	public static void main(String[] args) {
		// 1.时间知识普及:
		// 格林威治标准时间 标准开始时间: 1970.01.01 00:00:00 GMT
		// 中国:东八区时间 +8小时
		// 日本:东九区时间 +9小时

		// 2.创建Date对象
		Date d1 = new Date(); // 返回当前时区当前时间
		System.out.println(d1);
		Date d2 = new Date(0L); // 返回当前时区开始时间
		System.out.println(d2);

		// 3.设置时间
		d1.setTime(1000L); // 加1秒
		System.out.println(d1);
		// 4.获取时间
		long time1 = d1.getTime();
		System.out.println(time1); // 1000

		// 小练1: 获取当前时间和当前时间+1年
		Date d3 = new Date();
		long time2 = d3.getTime();
		Date d4 = new Date(time2 + 1000L * 60 * 60 * 24 * 365);
		System.out.println(d3);
		System.out.println(d4);
		// 小练2: 随机生成两个时间,判断日期大小
		Random random = new Random();
		Date d5 = new Date(Math.abs(random.nextInt()));
		Date d6 = new Date(Math.abs(random.nextInt()));
		long time3 = d5.getTime();
		long time4 = d6.getTime();
		System.out.println(d5);
		System.out.println(d6);
		if (time3 > time4) {
			System.out.println("第一个大");
		} else if (time4 > time3) {
			System.out.println("第二个大");
		} else {
			System.out.println("一样大");
		}
	}
}
SimpleDateFormat类

用于解析字符串转换成日期,或者格式化日期转换成字符串

package com.itheima.demo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTest {
    public static void main(String[] args) throws ParseException {
        // SimpleDateFormat作用
        // 1.格式化日期,返回字符串
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat();
        System.out.println(sdf.format(date));
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf2.format(date));

        // 2.解析字符串,返回日期,注意:解析内容必须和格式化内容保持一致
        Date date1 = sdf2.parse("2024-01-11 20:53:34");
        System.out.println(date1);

        // 字符串2011-11-11 -> 日期2011年11月11日
        String dateStr = "2011-11-11";
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy年MM月dd日");
        System.out.println(sdf4.format(sdf3.parse(dateStr)));

        // 秒杀时间是2023年11月11日 0:0:0 ~ 2023年11月11日 0:10:0
        String d1 = "2023年11月11日 0:0:0";
        String d2 = "2023年11月11日 0:10:0";
        String d3 = "2023年11月11日 0:1:0";
        String d4 = "2023年11月11日 0:11:0";
        SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date d11 = sdf5.parse(d1);
        Date d22 = sdf5.parse(d2);
        Date d33 = sdf5.parse(d3);
        Date d44 = sdf5.parse(d4);
        long start = d11.getTime();
        long end = d22.getTime();
        if (start <= d33.getTime() && end >= d33.getTime()) {
            System.out.println("小红参与了");
        } else {
            System.out.println("小红没参与了");
        }
        if (start <= d44.getTime() && end >= d44.getTime()) {
            System.out.println("小蓝参与了");
        } else {
            System.out.println("小蓝没参与了");
        }

        System.out.println(d11);
        System.out.println(d22);
    }
}
Calendar类
package com.itheima.demo;

import java.util.Calendar;
import java.util.Date;

public class CalendarTest {
    public static void main(String[] args) {
        // Calendar的出现是便于我们对时间的操作
        // 1.设置时间
        // 细节1:Calendar不是new出来的
        Calendar c1 = Calendar.getInstance(); // 默认发挥当前时区时间
        System.out.println(c1);
        c1.setTime(new Date(0L)); // 时间原点
        System.out.println(c1);
        c1.setTimeInMillis(1000L); // 时间原点+1秒
        System.out.println(c1);
        // 2.改变时间
        // 月份是0~11 星期从周日开始1~7
        c1.set(1, 2000); // 设置年为2000
        c1.set(2,11); // 设置月为12月
        System.out.println(c1);
        // 3.加减时间
        c1.add(2,1); // +一个月
        System.out.println(c1);
    }
}

JDK8版本相关

注意:JDK8的日期对象,为了线程安全,都是不可变的。对日期对象的操作都会生成一个新的日期对象。

ZoneId类
package com.itheima.demo;

import java.time.ZoneId;
import java.util.Set;

public class ZoneIdTest {
    public static void main(String[] args) {
        // 1.获取Java支持的所有时区
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        System.out.println(availableZoneIds);
        // 2.获取当前时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);
        // 3.指定一个时区
        ZoneId of = ZoneId.of("Africa/Monrovia");
        System.out.println(of);
    }
}
Instant类
package com.itheima.demo;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class InstantTest {
    public static void main(String[] args) {
        // 1.默认获取当前时间(无时区)
        Instant now = Instant.now();
        System.out.println(now);
        // 2.指定毫秒/秒/纳秒对应的无时区时间
        Instant instant = Instant.ofEpochMilli(0L);
        Instant instant1 = Instant.ofEpochSecond(1L);//+1
        Instant instant2 = Instant.ofEpochSecond(1L, 1000000000L);//+2
        System.out.println(instant);
        System.out.println(instant1);
        System.out.println(instant2);
        // 3.加入时区
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
        System.out.println(zonedDateTime);
        // 4.比较时间
        boolean before = instant.isBefore(instant1);
        System.out.println(before); // false
        boolean after = instant.isAfter(instant1);
        System.out.println(after);
        // 5.修改时间
        Instant instant3 = instant.plusMillis(1000L);
        System.out.println(instant3);
        Instant instant4 = instant.minusMillis(1000L);
        System.out.println(instant4);
    }
}

ZonedDateTime
package com.itheima.demo;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTimeTest {
    public static void main(String[] args) {
        // 1.获取当前时间(有时区)
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);
        // 2.指定有时区的时间(两种方式)
        ZonedDateTime of = ZonedDateTime.of(2024, 1, 14, 11, 12, 12, 0, ZoneId.systemDefault());
        ZonedDateTime of1 = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        System.out.println(of);
        System.out.println(of1);
        // 3.修改时间
        ZonedDateTime zonedDateTime = of.withYear(2025);
        System.out.println(zonedDateTime);
        // 4.减时间
        ZonedDateTime zonedDateTime1 = of.minusYears(1L);
        System.out.println(zonedDateTime1);
        // 5.加时间
        ZonedDateTime zonedDateTime2 = of.plusYears(1L);
        System.out.println(zonedDateTime2);
    }
}
DateTimeFormatter
package com.itheima.demo;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DateTimeFormatTest {
    public static void main(String[] args) {
        // 日期格式化类
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EE a");
        // 获取当前时区时间
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        // 格式化当前时区时间转换成字符串打印
        String format = dateTimeFormatter.format(zonedDateTime);
        System.out.println(format);
    }
}

LocalDate
package com.itheima.demo;

import java.time.LocalDate;
import java.time.Month;

public class LocalDateTest {
    public static void main(String[] args) {
        // 1.获取当前日期
        LocalDate now = LocalDate.now();
        System.out.println(now);// 2024-1-15
        // 2.设置日期
        LocalDate of = LocalDate.of(2024, 1, 15);
        System.out.println(of);// 2024-1-15
        // 3.获取日期信息
        int year = of.getYear();
        Month month = of.getMonth();
        int value = month.getValue();
        System.out.println(year);// 2024
        System.out.println(value);// 1
        // 4.设置日期信息
        LocalDate localDate = of.withYear(2025);
        System.out.println(localDate);// 2025-1-15
        // 5.加日期信息
        LocalDate localDate1 = of.minusYears(1);// 2023-1-15
        System.out.println(localDate1);
        // 6.减少日期信息
        LocalDate localDate2 = of.plusYears(1); // 2025-1-15
        System.out.println(localDate2);
    }
}
LocalTime
package com.itheima.demo;

import java.time.LocalTime;

public class LocalTimeTest {
    public static void main(String[] args) {
        // 1.获取当前时间
        LocalTime now = LocalTime.now();
        System.out.println(now); // 19:27...
        // 2.指定时间
        LocalTime of = LocalTime.of(20, 30, 10, 1);
        System.out.println(of);//20:30:10.000000001
        // 3.设置时间信息
        LocalTime localTime = of.withHour(21);
        System.out.println(localTime);//21:30:10.000000001
        // 4.获取时间信息
        int hour = of.getHour();
        System.out.println(hour);//20
        // 5.加时间信息
        LocalTime localTime1 = of.plusHours(1);
        System.out.println(localTime1);//21:30:10.000000001
        // 6.减时间信息
        LocalTime localTime2 = of.minusHours(1);
        System.out.println(localTime2);//19:30:10.000000001
    }
}
LocalDateTime
package com.itheima.demo;

import java.time.LocalDateTime;

public class LocalDateTimeTest {
    public static void main(String[] args) {
        // 1.获取当前日期时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);// 2024-1-15T19:34:1 ...
        // 2.指定日期时间
        LocalDateTime of = LocalDateTime.of(2024, 1, 15, 19, 34, 1, 1);
        System.out.println(of);// 2024-1-15T19:34:1 000000001
        // 3.设置日期时间信息
        LocalDateTime localDateTime = of.withHour(20);
        System.out.println(localDateTime);// 2024-1-15T20:34:1 000000001
        // 4.获取日期时间信息
        int value = of.getMonth().getValue();
        System.out.println(value);// 1
        // 5.加日期时间信息
        LocalDateTime localDateTime1 = of.plusMonths(1);
        System.out.println(localDateTime1); // 2024-2-15T19:34:1 000000001
        // 6.减日期时间信息
        LocalDateTime localDateTime2 = of.minusMonths(1);
        System.out.println(localDateTime2);// 2023-12-15T19:34:1 000000001
    }
}
Duration
package com.itheima.demo;

import java.time.Duration;
import java.time.LocalDateTime;

public class DurationTest {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime bir = LocalDateTime.of(1999, 5, 29, 0, 0);
        // 1.记录两个日期时间的差值(时,分,秒)
        Duration between = Duration.between(bir, now);
        System.out.println(between);
        // 2.不同单位下的差值
        long l1 = between.toDays(); // 天
        System.out.println(l1);
        long l = between.toHours(); // 小时
        System.out.println(l);
        long l2 = between.toMinutes(); // 分钟
        System.out.println(l2);
        long l3 = between.toSeconds(); // 秒
        System.out.println(l3);

    }
}
Period
package com.itheima.demo;

import java.time.LocalDateTime;
import java.time.Period;

public class PeriodTest {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime bir = LocalDateTime.of(1999, 5, 29, 0, 0);
        // 1.日期差值对象(年,月,日)
        Period between = Period.between(bir.toLocalDate(), now.toLocalDate());
        System.out.println(between);
        // 2.不记录整体差值
        int years = between.getYears();
        int months = between.getMonths();
        int days = between.getDays();
        System.out.println(years);
        System.out.println(months);
        System.out.println(days);
        /**
         * 结果案例
         * P24Y7M17D
         * 24
         * 7
         * 17
         */
    }
}
ChronoUnit
package com.itheima.demo;

import java.time.LocalDateTime;
import java.time.MonthDay;
import java.time.temporal.ChronoUnit;

public class ChronoUnitTest {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime bir = LocalDateTime.of(1999, 5, 29, 0, 0);
        // 各个单位下的差值比较
        long between = ChronoUnit.YEARS.between(bir, now);
        long between1 = ChronoUnit.MONTHS.between(bir, now);
        long between2 = ChronoUnit.DAYS.between(bir, now);
        long between3 = ChronoUnit.HOURS.between(bir, now);
        long between4 = ChronoUnit.MINUTES.between(bir, now);
        long between5 = ChronoUnit.SECONDS.between(bir, now);
        System.out.println(between);
        System.out.println(between1);
        System.out.println(between2);
        System.out.println(between3);
        System.out.println(between4);
        System.out.println(between5);

        System.out.println("==========拓展API==========");
        // 只关注月份和天
        MonthDay bir1 = MonthDay.of(5, 29);
        MonthDay now1 = MonthDay.from(now);
        System.out.println(bir1.equals(now1));
    }
}

包装类

Integer装箱和拆箱

package com.itheima.demo;

public class IntegerTest {
    public static void main(String[] args) {
        // 1.什么是包装类
        // 基本数据类型对应的类
        Integer i = Integer.valueOf(10); // 装箱操作,把int装入Integer对象中
        int j = i.intValue(); // 拆箱操作,把Integer对象拆成int
        Integer result = Integer.valueOf(i.intValue() + j);
        System.out.println(result);
        // 2.JDK5后,包装类引入了什么新特性
        // 实现了自动装箱和自动拆箱
        Integer i1 = 10;
        int j1 = i1;
        Integer result1 = i1 + j1;
        System.out.println(result1);
    }
}

Integer的进制转换和字符串解析

package com.itheima.demo;

public class Integer2Test {
    public static void main(String[] args) {
        // 1.十进制转换成其他进制字符串
        String s1 = Integer.toBinaryString(100); //110010
        String s2 = Integer.toOctalString(100); // 144
        String s3 = Integer.toHexString(100); // 64
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        // 2.字符串解析成其他数据类型
        Integer num = Integer.parseInt("100"); // 必须是数字,否则报异常
        Double num1 = Double.parseDouble("100");
        System.out.println(num + num1); //200.0
    }
}

算法基础(Day21)

查找算法

基本查找(顺序查找)

数据不要求有序

二分查找

要求是有序数据

package com.itheima.demo;

public class TwoDivideTest {
    public static void main(String[] args) {
        // 1.定义一个有序的数组
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        // 2.要查询的数据
        int search = 3;
        // 3.查询数据对应的下标
        int index = -1;
        // 4. 查询的次数
        int count = 0;
        // 5. 索引最小值
        int min = 0;
        // 6. 索引最大值
        int max = nums.length - 1;
        while (true) {
            // 查询次数+1
            count++;
            // 如果索引最小值大于最大值结束查询
            if (min > max) {
                break;
            } else {
                // 中间索引
                int middle = (min + max) / 2;
                if (search < nums[middle]) {
                    // 查询数据 在 中间索引值 左侧 max = middle - 1
                    max = middle - 1;
                } else if (search == nums[middle]) {
                    // 查询数据 等于 中间索引值 结束最小值查询
                    index = middle;
                    break;
                } else {
                    // 查询数据 在中间索引值 右侧 min = middle + 1
                    min = middle + 1;
                }
            }
        }
        System.out.println(index);
        System.out.println(count);
    }
}

插值查找

要求数据有序,适用于有序且分布均匀的数据

package com.itheima.demo;

/**
 * 插值查找
 */
public class InterpolationSearchTest {
    public static void main(String[] args) {
        // 1.定义一个有序(间隔均匀)的数组
        int[] nums = {0, 2, 4, 6, 7, 9};
        // 2.定义要查找的值
        int searchNum = 6;
        // 3.定义下标最小值
        int minIndex = 0;
        // 4.定义下标最大值
        int maxIndex = nums.length - 1;
        // 5. 定义查询值索引
        int searchIndex = -1;
        int count = 0;
        while (true) {
            count++;
            // 6.如果最小索引大于最大索引 未找到结束查询
            if (minIndex > maxIndex) {
                break;
            }
            // 7.定义自适应中间下标
            // 7.1 最小值下标(偏移量) + ((查询值-最小值)/(最大值-最小值)) * (最大值下标 - 最小值下标)
            int autoIndex = minIndex + (searchNum - nums[minIndex]) * (maxIndex - minIndex) / (nums[maxIndex] - nums[minIndex]);
            if (nums[autoIndex] == searchNum) {
                searchIndex = autoIndex;
                break;
            } else if (searchIndex < nums[autoIndex]) {
                maxIndex = autoIndex - 1;
            } else {
                minIndex = autoIndex + 1;
            }
        }
        System.out.println(searchIndex);
        System.out.println(count);
    }
}

分块查找

要求块间不相交,块内无序
情况1:块间有序

package com.itheima.demo;

public class PiecemealSearchTest {
    public static void main(String[] args) {
        // 1.定义一个不完全有序的数据
        int[] nums = {5, 3, 4, 2, 1,
                10, 8, 7, 6, 9,
                11, 15, 16, 13, 14};
        // 2.分为有序块
        Piece piece = new Piece(5, 0, 4);
        Piece piece1 = new Piece(10, 5, 9);
        Piece piece2 = new Piece(16, 10, 14);
        // 3.创建索引表
        Piece[] pieces = {piece, piece1, piece2};
        // 4.查询值
        int searchNum = 16;
        // 5.获取查询值下标
        int searchIndex = getIndex(searchNum, nums, pieces);
        // 6.打印查询值
        System.out.println(searchIndex);
    }

    private static int getIndex(int searchNum, int[] nums, Piece[] pieces) {
        // 7.获取指定块
        Piece piece = getPiece(searchNum, pieces);
        if (piece == null) {
            return -1;
        }
        // 8.顺序查找获取下标
        for (int i = piece.startIndex; i <= piece.endIndex; i++) {
            if (nums[i] == searchNum) {
                return i;
            }
        }
        // 9.找不到返回-1
        return -1;
    }

    private static Piece getPiece(int searchNum, Piece[] pieces) {
        // 顺序遍历索引表
        for (Piece piece : pieces) {
            if (searchNum <= piece.max) {
                return piece;
            }
        }
        return null;
    }
}

class Piece {
    int max;
    int startIndex;
    int endIndex;

    public Piece(int max, int startIndex, int endIndex) {
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
}

情况2:块间无序

package com.itheima.demo;

public class PiecemealSearchTest1 {
    public static void main(String[] args) {
        // 1.定义无序的数据
        int[] nums = {9, 8, 7, 6, 2, 3, 4, 5, 10, 15, 13, 16, 20, 18, 19};
        // 2.分块无交集
        Piece1 piece1 = new Piece1(6, 9, 0, 3);
        Piece1 piece11 = new Piece1(2, 5, 4, 7);
        Piece1 piece12 = new Piece1(10, 15, 8, 11);
        Piece1 piece13 = new Piece1(16, 20, 12, 15);
        // 3.创建索引表
        Piece1[] piece1s = {piece1, piece11, piece12, piece13};
        // 4.定义查找值
        int searchNum = 21;
        // 5.获取查找值下标
        int searchIndex = getIndex(searchNum, nums, piece1s);
        // 6.打印下标
        System.out.println(searchIndex);
    }

    private static int getIndex(int searchNum, int[] nums, Piece1[] piece1s) {
        // 7.获取指定块
        Piece1 piece1 = getPiece(searchNum, piece1s);
        // 8. 顺序遍历块获取下标
        if (piece1 == null) {
            return -1;
        }

        for (int i = piece1.startIndex; i <= piece1.endIndex; i++) {
            if (nums[i] == searchNum) {
                return i;
            }
        }
        return -1;
    }

    private static Piece1 getPiece(int searchNum, Piece1[] piece1s) {
        for (Piece1 piece1 : piece1s) {
            if (searchNum <= piece1.max && searchNum >= piece1.min) {
                return piece1;
            }
        }
        return null;
    }
}

class Piece1 {
    int min;
    int max;
    int startIndex;
    int endIndex;

    public Piece1(int min, int max, int startIndex, int endIndex) {
        this.min = min;
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
}

排序算法

冒泡排序

思想:一组数据,从左到右两两比较,小的放前,大的放后

	/**
	 * 冒泡排序
	 * 
	 * @param nums
	 * @return
	 */
	public static int[] maoPao(int[] nums) {
		int count = 0;
		for (int i = 0; i < nums.length - 1; i++) {
			for (int j = 0; j < nums.length - 1 - i; j++) {
				count++;
				if (nums[j] > nums[j + 1]) {
					int temp = nums[j];
					nums[j] = nums[j + 1];
					nums[j + 1] = temp;
				}
			}
		}
		System.out.println("冒泡count:" + count);
		return nums;
	}
选择排序

思想:一组数据从索引0开始,索引0与后面的数据依次比较,小的放前,大的放后

/**
	 * 选择排序
	 * 
	 * @param nums
	 * @return
	 */
	public static int[] xuanZe(int[] nums) {
		int count = 0;
		for (int i = 0; i < nums.length - 1; i++) {
			for (int j = i + 1; j < nums.length; j++) {
				count++;
				if (nums[i] > nums[j]) {
					int temp = nums[i];
					nums[i] = nums[j];
					nums[j] = temp;
				}
			}
		}
		System.out.println("选择count:" + count);
		return nums;
	}
插入排序

思想:将数组分为有序和无序的两组数据,无序数据从右往左依次比较有序数据,插入合适位置

/**
	 * 插入排序
	 * 
	 * @param nums
	 * @return
	 */
	public static int[] chaRu(int[] nums) {
		int count = 0;
		for (int i = 0; i < nums.length - 1; i++) {
			for (int j = i; j >= 0; j--) {
				count++;
				if (nums[j] > nums[j + 1]) {
					int temp = nums[j];
					nums[j] = nums[j + 1];
					nums[j + 1] = temp;
				} else {
					break;
				}
			}
		}
		System.out.println("插入count:" + count);
		return nums;
	}

递归算法
	/**
	 * 累加递归
	 * 
	 * @param num
	 * @return
	 */
	public static int leiJia(int num) {
		if (num > 1) {
			return num + leiJia(num - 1);
		} else {
			return num;
		}
	}
快速排序

思想:以数组开始索引元素为基准数,数组首先从右向左找小于基准数的停下,然后从左往右找大于基准数的停下,两者交换,当两个寻找下标相同时,与基准数替换,称基准数归位,基准数的左右两边进行重复的递归操作,当开始下标大于结束下标时,结束递归

/**
	 * 快速排序
	 * 
	 * @param nums
	 * @return
	 */
	public static void kuaiSu(int[] nums, int start, int end) {
		if (start > end) {
			return;
		}
		int i = start;
		int j = end;
		// 注意:如果基准数时索引0的值,则必须先移动end,再移动start
		int index1 = start;
		while (start < end) {
			if (nums[end] > nums[index1]) {
				end--;
				continue;
			}
			if (nums[start] < nums[index1]) {
				start++;
				continue;
			}
			int temp = nums[start];
			nums[start] = nums[end];
			nums[end] = temp;
		}
		int temp = nums[index1];
		nums[index1] = nums[end];
		nums[end] = temp;

		kuaiSu(nums, i, start - 1);
		kuaiSu(nums, start + 1, j);
	}

Lambda表达式

  1. Lambda表达式的作用?
    简化了匿名内部类的创建
  2. Lambda表达式使用前提?
    匿名内部类必须是有且仅有一个抽象方法接口,才可以使用Lambda表达式
  3. Lambda表达式好处?
    使得代码更简洁、更灵活、更紧凑
  4. 完整格式:(参数类型 参数名)->{return xxxx;}
  5. 省略格式:参数名->xxxx
package com.itheima.demo;

public class LambdaTest {
	public static void main(String[] args) {
		// 匿名内部类
		swimming(new Swim() {
			@Override
			public void swimming() {
				System.out.println("swimming...");
			}
		});
		System.out.println("----------------------");
		// Lambda表达式
		swimming(() -> {
			System.out.println("swimming...");
		});
	}
	public static void swimming(Swim swim) {
		swim.swimming();
	}
}

interface Swim {
	void swimming();
}

集合进阶(Day22)

单列集合顶层接口(Collection)

	/**
	 * 1.单列集合顶层接口入门
	 */
	public static void CollectionInit() {
		Collection<Student> list = new ArrayList<>();
		// 1.添加元素 boolean add(E e)
		// 细节1:Set添加重复元素时为false
		list.add(new Student("张三", 18));
		list.add(new Student("李四", 20));
		list.add(new Student("张三", 18));
		System.out.println(list);
		// 2.清空集合 clear()
//		list.clear();
//		System.out.println(list);
		// 3.删除元素 boolean remove(E e)
		list.remove(new Student("张三", 18));
		System.out.println(list);
		// 4.是否包含元素 boolean contains(Object obj)
		System.out.println(list.contains(new Student("张三", 18)));
		// 5.列表是否为空
		System.out.println(list.isEmpty());
		// 6.列表的长度
		System.out.println(list.size());
	}

迭代器(Iterator)

使用场景:遍历过程中需要删除元素时使用

/**
	 * 2.迭代器遍历
	 * 
	 * @return
	 */
	public static void iteratorTest() {
		Collection<Student> list = new ArrayList<>();
		list.add(new Student("张三", 18));
		list.add(new Student("李四", 20));

		// 1.获取Iterator
		// 细节:Iterator方式遍历,不依赖索引,通过创建指针,移动指针实现遍历
		Iterator<Student> iterator = list.iterator();
		// 2.指针指向存在元素
		while (iterator.hasNext()) {
			// 3.获取指针元素,移动指针
			Student student = iterator.next();
			System.out.println(student);
			try {
//				list.remove(student);
				iterator.remove();
			} catch (Exception e) {
				// ConcurrentModificationException
				e.printStackTrace();
			}
		}
		try {
			// 细节1:指针指向不存在元素情况下,获取指针元素 报NoSuchElementException
			// 细节2:next不会归位,迭代器遍历没有回头路
			// 细节3:while中不应该存在多个next,可能会包NoSuchElementException
			// 细节4:不能再遍历过程中用集合的方式增删数据,可以用迭代器自带的方法进行删除
			iterator.next();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

增强For和Lambda表达式

场合:适用于仅遍历的场合使用

/**
	 * 3.增强for遍历
	 */
	public static void forTest() {
		Collection<Student> list = new ArrayList<>();
		list.add(new Student("张三", 18));
		list.add(new Student("李四", 20));
		// 增强for
		// 1.作用 简化迭代器代码的书写
		// 2.底层 就是迭代器遍历
		// 3.使用范围 单列集合和数组
		// 4.JDK支持版本 JDK5+
		for (Student student : list) {
			// 细节1: 修改for的变量内部属性会改变list中的值
			student.setAge(student.getAge() + 1);
			// 细节2: 修改for的变量本身不会改变集合中的值
			student = new Student("张三", 20);
		}
		for (Student student : list) {
			System.out.println(student);
		}
		System.out.println("-------------------------------------");
		// Lambda表达式遍历JDK8+
		// 匿名内部类方式遍历list集合
		list.forEach(new Consumer<Student>() {
			@Override
			public void accept(Student student) {
				System.out.println(student);
			}
		});
		System.out.println("-------------------------------------");
		// Lambda表达式方式遍历list集合
		list.forEach(student -> System.out.println(student));
	}

单列有序集合接口(List)

List的存取是有序的,数据可以重复,有索引

	/**
	 * 4.单列集合List
	 */
	public static void listTest() {
		List<Student> list = new ArrayList<>();
		// 1. 指定下标添加数据
		list.add(new Student("张三", 18));
		list.add(new Student("王五", 22));
		list.add(1, new Student("李四", 20));
		System.out.println(list);
		// 2. 指定下标设置数据
		System.out.println("-------------------------------------");
		list.set(1, new Student("李四1", 20));
		System.out.println(list);
		// 3. 指定下标删除
		System.out.println("-------------------------------------");
		list.remove(1);
		System.out.println(list);
		// 4. 获取指定下标值
		System.out.println("-------------------------------------");
		System.out.println(list.get(1));
	}

单列集合List遍历特有方式

使用场景:

  1. 需要索引时,用普通for循环遍历
  2. 需要再遍历时,添加数据时,用列表迭代器遍历
	/**
	 * 5.单列集合List特有遍历
	 */
	public static void listIteratorTest() {
		List<Student> list = new ArrayList<>();
		list.add(new Student("张三", 18));
		list.add(new Student("王五", 22));
		list.add(1, new Student("李四", 20));
		// 普通for循环遍历
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("-------------------------------------");
		// 列表迭代器遍历
		ListIterator<Student> iteratorList = list.listIterator();
		while (iteratorList.hasNext()) {
			System.out.println(iteratorList.next());
			iteratorList.add(new Student("老刘", 25));
		}
		System.out.println("-------------------------------------");
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}

数据结构

  1. 栈:先进后出
  2. 队列:先进先出
  3. 数组(数据在内存中的存储是连续的)
    查询速度快(初始地址值+索引)
    删除效率低(原始数据删除,后面数据前移)
    插入效率低(插入位置后面数据后移,再插入元素)
  4. 链表
    链表的各个节点在内存中的存储时不连续的
    查询速度低(所有的查询都要从头开始查询)
    删除效率高(相较于数组)
    插入效率高(相较于数组)

ArrayList的扩容机制

  1. ArrayList的数据存储底层是数组
  2. 对于创建空参的ArrayList,底层数组长度为0
  3. 第一次加入数据时,底层数据会进行扩容 首次扩容为10 一次加入数据超出10 则扩容为加入数据长多
  4. 当首次扩容数组被填满再次添加数据, 底层数组会扩容1.5倍,若加入数据超出1.5倍(10->15),则扩容为加入(数据长度+底层数组原长)

LinkedList区别与ArrayList

  1. LinkedList的底层是双向链表 链表结点在堆内存的存储是不连续的
  2. 其中有头结点和尾结点开始都为null
  3. 如果添加一个结点,则头尾结点都存储该结点的地址值
  4. 如果再添加一个结点,则尾结点等于添加的结点,且添加结点创建时,填充前个结点为原尾结点地址,原尾结点的下一个结点则存在新结点地址

iterator迭代器底层

  1. list.iterator()是创建时,当前下标为0 上一轮下标为-1
  2. iterator.hasNext()是判断当前下标!=size则为true
  3. iterator.next()是让当前下标后移一位,上一轮下标为原当前下标,并返回原当前下标对应的数据

泛型

  1. 应用场景:
    当定义一个类、方法、接口的数据类型不确定,可以使用泛型类,泛型方法,泛型接口
    泛型类在定义对象的时候确定数据类型
    泛型方法在调用方法的时候确定数据类型
    泛型接口在定义实现类确定泛型
  2. 泛型什么时候出现的,泛型出现的作用或好处
    泛型在JDK5出现
    JDK5之前都是Object,泛型出现后,不仅在编译阶段约束数据类型,还将运行阶段可能出现的强转报错提前至编译阶段,泛型在确定类型后,可以存储本类及其子类,泛型出现可以调用泛型类的特有行为
  3. 如果类型希望是某个类的子类(包括它自己)或者父类(包括它自己)可以用? extends 类名? super 类名,其中?是泛型通配符
  4. 注意泛型不能是基本数据类型,只能使用基本数据类型的包装类
// 所有的方法都可以用这个泛型
// 泛型类:泛型定义在类名后面的类
// 同理 泛型接口:泛型定义在接口名后面的接口
class MyArrayList<E> {
	Object[] objs = new Object[10];
	int size;

	void add(E e) {
		objs[size++] = e;
	}

	@SuppressWarnings("unchecked")
	E get(int index) {
		return (E) objs[index];
	}
	// 泛型方法:泛型定义在方法修饰符后面的方法
	<T> void show(T t) {
		System.out.println("Hello " + t);
	}

	@Override
	public String toString() {
		return Arrays.toString(objs);
	}
}

相关名词:
父节点
左子节点
右子节点
度:子节点的数目
二叉树:任意节点的度都小于或等于2
树高:总层数
左子树
右子树

二叉树的演变

1.普通的二叉树数据存储是无规律的
2.查找二叉树也称搜索二叉树,排序二叉树,遵循的规则是数据大小左节点 < 当前节点 < 右节点
3.二叉树遍历方式:
前序遍历 当前节点 左子树 右子树
中序遍历 左子树 当前节点 右子树
后序遍历 左子树 右子树 当前节点
层序遍历 按层遍历
4.平衡二叉树 任意节点的左子树和右子树层数差小于等于1

平衡二叉树的旋转机制

平衡二叉树有左旋和右旋两种方式,不平衡点降阶为左子树时,原左子树作为不平衡点的右子树,降为右子树时,原右子树作为不平衡点的左子树。
对于插入平衡二叉树的节点进行旋转的情况分为四类:
左左:不平衡点的左子节点的左子树上追加数据,不平衡点仅需要一次右旋完成
左右:不平衡点的左子节点的右子树上追加数据,左子节点完成一次左旋后,不平衡完成一次右旋完成
右右:不平衡点的右子节点的右子树上追加数据,不平衡点仅需要一次左旋完成
右左:不平衡点的右子节点的左子树上追加数据,右子节点完成一次右旋后,不平衡完成一次左旋完成

红黑树

红黑树的特点:

  1. 所有的节点只能是黑色或者红色
  2. 根节点必定为黑色
  3. 节点之间不可能红红相连
  4. 如果一个节点没有子节点或者父节点,则将会指向Nil节点,Nil节点也会视叶节点,Nil节点一定是黑色
  5. 任意一个节点到后代叶节点的简单路径,黑色节点的数目完全一致

红黑树添加节点的规则:

  • 添加的节点默认设置为红色
  • 若添加的节点为根节点 则直接变成黑色
  • 若添加的节点不是根节点则分情况讨论
  • 若添加的节点的父节点是黑色,不做任何操作
  • 若添加的节点的父节点是红色则分情况讨论
  • 若添加的节点的叔叔节点为红色,则叔叔节点和父节点都变为黑色,祖父节点变为红色,如果祖父节点是根节点则变为黑色,若不是根节点,祖父节点作用目标节点进一步处理
  • 若添加的节点的叔叔节点为黑色,且添加节点为左子节点时,父节点变为黑色,祖父节点变为红色,以祖父节点进行右旋(左左,右右)
  • 若添加的节点的叔叔节点为黑色,且添加节点为右子节点时,以父节点进行左旋,并将原父节点作为目标节点进一步处理(左右,右左)

Set系列集合

List集合和Set集合之间的区别?
List集合:有序,可重复,有索引
Set集合:无序,不重复,无索引

无序?
存取顺序不一致

Set集合的实现类

  1. HashSet: 无序,不重复,无索引
  2. LinkedHashSet: 有序,不重复,无索引
  3. TreeSet: 可排序,不重复,无索引
HashSet
  1. 底层:初始化时长度为16,加载因子0.75的数组,叫table
  2. HashSet在增加元素时,首先根据哈希值&(数组长度-1)确定插入下标,如果下标没有数据,则直接填入,若有数据则(JDK7)新数据连接旧数据,(JDK8)旧数据连接新数据
  3. 之所以存取不一致,是因为取时,从下标零开始遍历,每个元素遍历完毕才取下一个索引数据
  4. 因为底层数据结构问题,JDK8更是加入了红黑树,所以没有索引
  5. HashSet保证去重的原理是,重写了equals和hashCode方法,保证了在属性完全相同的时候,插入的数据会和插入索引的链表进行equals比较,相同则不插入
  6. JDK8在底层链表长度大于8并且数组长度大于64时,变成红黑树
LinkedHashSet

加入了双向链表属性,保证了前后数据的关联性,保证了数据的存取时有序的

TreeSet
  1. TreeSet底层是红黑树
  2. 对于数值类型的数据,默认按照升序排列,Integer,Double,Float实现了Comparable方法
  3. 对于字符或者我字符串的数据,默认按照Ascii码进行升序排列
  4. 对于存储的数据是自定义类对象,要求该类必须实现Comparable接口,重写compareTo方法,自定义排序规则,否则报运行时异常
  5. 当默认的Comparable接口的排序不满足需求时,可以使用TreeSet(Comparator comparator)构造方法进行排序
  6. 实现方法compareTo(T t)/compare(T t1,T t2),返回负数,放在红黑树左边,返回正数,放在红黑树右边,返回零表示重复数据,不添加
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自律最差的编程狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值