JAVA三大版本

  • J2SE 占领桌面程序, 控制台开发 标准版
  • J2ME 占领手机,小家电 嵌入式开发
  • J2EE 占领服务器,web端 企业级开发

三高

  • 高并发
  • 高可用
  • 高性能

Java特性和优势

  • 简单性
  • 面向对象
  • 可移植性(跨*台)
  • 高性能
  • 分布式
  • 动态性(反射)
  • 多线程
  • 安全性(异常机制)
  • 健壮性

JDK, JRE, JVM

JDK

  • java development kit java开发者工具(java, javac, javadoc, jar)
  • jdk包含jre

JRE

  • java runtime environment java运行环境(函数库, 虚拟机)

JVM

  • java virtual machine java虚拟机 (模拟cpu)

安装开发环境

  • jdk下载与安装
# 下载jdk8
# 卸载原有的
    # 删除文件包
    # 清理环境变量 JAVA_HOME 和 path下的关于java的
    # java -version 检查是否删除
# 安装运行文件
  • 配置环境变量
# 添加环境变量 系统变量
# 新建JAVA_HOME
路径: F:java\jdk8
# 配置Path变量
# 新建
%JAVA_HOME%\bin
%JAVA_HOME%\jre\bin

# 检查安装
# java -version
# java
# javac
  • 目录解析
# bin 可执行文件
# include 存放C语言头文件
# jre java运行环境
# lib java开发库文件

HelloWorld

  • 新建Hello.java
  • 类名Hello必须和文件名一致
public class Hello{
    public static void main(String[] args){
        System.out.println("Hello,World!");
    }
}
  • 命令行窗口
# 当前hello.java文件目录下
# javac编译成.class文件
javac Hello.java
# 运行java程序
java Hello

JAVA程序运行机制

编译型

  • 比如: 将一本中文书翻译成英文,
  • 编译器
  • 速度快

解释型

  • 比如: 翻译官, 想要翻译那句,就翻译那句
  • 解释器
  • 一行一行解释
  • 性能消耗. 速度慢

程序运行机制

java 摘要算法应用场景_System

IDEA安装

  • 下载安装文件
  • 选择64位和.java

JAVA基础语法

注释

//单行注释

/*
    多行注释
    多行注释
*/

/**
 * 文档注释
 *
 * @author  cyz
 * @create 2020/07/10 18-30
 */

标识符

java 所有的组成部分都需要名字, 类名, 变量名以及方法都被称为标识符
    
以字母, 美元符号($), 下划线, 数字 组成
不能以数字开头
不能使用关键字作为变量名或方法名
大小写敏感
可以使用中文, 但不建议

关键字

java的特殊标识符: public static void class

数据类型

  • java是强类型语言: 先定义才能使用
基本类型
	数值类型:
			整数类型: byte    1字节
             	      short   2字节
                	  int     4字节
                	  long(L)    8字节
             浮点类型: float(F)   4字节
                 	  double  8字节
             字符类型: char    2字节
     boolean类型: 占1位 true/false
引用类型:

类: String

接口:

数组:

常见问题

//整数拓展 进制问题
二进制0b:  int i = 10010b;
十进制:    int i2 = 10;
八进制0:   int i3 = 010;
十六进制0x: int i4 = 0x10;
//浮点数拓展

银行业务表示: BigDecimal(数学工具类)

float f = 0.1f;//0.1

double d = 1.0/10;//0.1

System.out.println(f == d);//false
float f1 = 233333123212f;

float f2 = f1 + 1;

System.out.println(f1 == f2);//true
//float: 有限 离散  舍入误差 大约 接*等

//double:
//字符拓展

char c1 = 'a';

char c2 = '中';

System.out.println(c1);//a

System.out.println((int)c1);//97

System.out.println(c2);//中

System.out.println((int)c1);//20013

//所有字符本质是数字

//编码 Unicode 2字节
//转义字符

\t //制表符

\n //换行
//布尔值扩展

boolean flag = true;

if(flag==true){}

it(flag){}//等价

类型转换

  • 强类型转换 高-->低
  • 自动类型转换 低-->高
byte,short,char---->int--->long--->float--->double
int i = 128;

byte b = (byte)i;//-128 内存溢出
/*

注意点:

1. 不能转换boolean类型

2. 高容量转为低容量, 强制转换

3. 不能把对象类型转为不相干的类型

4. 转换时注意内存溢出和精度问题

*/
//jdk7新特性: 数字分割

int money 10_0000_0000;

int years = 20;

int total = moneyyears;

System.out.println(total);// -1474836480 计算时候溢出

long tota2 = moneyyears;// 默认是int 转换前就出错了

System.out.println(tota2);// -1474836480 计算时候溢出
//解决

long total = money*((long)years);

变量

// 可变化的量
变量类型 变量名 = 变量值;
变量类型 变量名=变量值, 变量名=变量值,...;//不建议  程序可读性

变量作用域

  • 类变量: static修饰
  • 实例变量 定义在类中但不在方法中
  • 默认值: 0, 0.0, null, false
  • 局部变量: 定义在方法中

常量

// 不可变的值 final修饰
final double PI = 3.14;

运算符

# 算术运算符: +, -, *, /, ++, --
# 赋值运算符: =
# 关系运算符: >, <, >=, <=, ==, !=, instanceof
# 逻辑运算符: &&, ||, !  (断路问题)
# 位运算符: &, |, ^, ~, >>, <<, >>>
# 条件运算符: ? :
# 扩展赋值运算符: +=, -=, *=, /=
28 =16 # 怎么最快  2222

2<<3

<< : *2 # 乘2

>> : /2 # 除2
  • 连接符
    ("" + a + b) 和 (a + b + "") 的区别: ""在前面先拼接, 在后面先运算

包机制

// 用于区别类名的命名空间
// 一般使用公司域名倒置作为包名
//命名及导入

package 包名;

import 包名;
//阿里巴巴开发手册

JavaDoc

//生成API文档
//参数信息
@author 作者名
@version 版本号
@since 指明需要最早使用的jdk版本
@param 参数名
@return 返回值情况
@throws 异常抛出情况
// 命令行生成文档

javadoc -encoding UTF-8 -charset UTF-8 Doc.java

//打开 index.html

用户交互Scanner

//next() 空白为结束符
Scanner scanner = new Scanner(System.in);
System.out.println("请输入的内容: ");//hello world
if(scanner.hasNext()){
    String str = scanner.next();
    System.out.println("输入的内容为: " + str);//hello
}
scanner.close();//关闭资源 减少资源占用
//nextLine()  回车为结束符

Scanner scanner = new Scanner(System.in);

System.out.println("请输入的内容: ");//hello world

if(scanner.hasNextLine()){

String str = scanner.nextLine();

System.out.println("输入的内容为: " + str);//hello world

}

scanner.close();//关闭资源 减少资源占用
// 省略判断

Scanner scanner = new Scanner(System.in);

System.out.println("请输入的内容: ");//hello world

String str = scanner.nextLine();

System.out.println("输入的内容为: " + str);//hello world

scanner.close();//关闭资源 减少资源占用
Scanner scanner = new Scanner(System.in);
int i = 0;
float f = 0.0f;
System.out.println("请输入整数: ");
if(scanner.hasNextInt()){
    i = scanner.nextInt();
    System.out.println("输入的整数为: " + i);
}else{
     System.out.println("输入的不是整数");
}

System.out.println("请输入小数: ");
if(scanner.hasNextFloat()){
    f = scanner.nextFloat();
    System.out.println("输入的小数为: " + f);
}else{
     System.out.println("输入的不是小数");
}
scanner.close();//关闭资源 减少资源占用

顺序结构

//一句一句执行

选择结构

if单选择结构

if (布尔表达式){
    //布尔表达式为true执行的语句
}

if双选择结构

if (布尔表达式){
    //布尔表达式为true执行的语句
}else {
    //布尔表达式为false执行的语句
}

if多选择结构

if (布尔表达式1) {
    //布尔表达式1为true执行的语句
}else if (布尔表达式2) {
    //布尔表达式2为true执行的语句
}else if (布尔表达式3) {
    //布尔表达式3为true执行的语句
}else {
    //布尔表达式都不为true执行的语句
}

嵌套的if结构

if (布尔表达式1) {
    if (布尔表达式2) {
    	//布尔表达式1为true的前提下 布尔表达式2为true执行的语句
	}
}

switch多选择结构

switch(expression){
    case value :
        //语句
        break;
    case value :
        //语句
        break;
    default :
        //语句
}
//case穿透

//switch 变量类型可以是 :byte, short, int, char, String

//case 必须是字符串常量或字面量

循环结构

while

while( 布尔表达式 ){
    //布尔表达式为true执行语句
}
while(true){
}

do...while

do {
    //代码语句
}while( 布尔表达式 );
//至少执行一次

for

for(初始化; 布尔表达式; 更新){
    //代码语句
}
for( ; ; ){
}

增强for

for(声明语句 : 表达式){
    //代码语句
}
int[] numbers = {10,20,30,40,50};

for(int x : numbers){

System.out.println(x);

}

break&continue

// break 退出整个循环
// continue 退出某次循环
//通过标记跳出某个指定循环

方法

  • 功能块: 实现某额功能的语句块集合
修饰符 返回值类型 方法名(参数类型 参数名){
    ...
        方法体
    ...
    return 返回值;
}
// 形参和实参

//java 值传递(拷贝的) 没有 引用传递

方法重载

  • 方法名相同
  • 参数类型, 参数个数, 参数顺序, 不同

可变参数

  • 参数类型后加一个(...)
  • 一个方法中只能有一个, 且为最后一个参数
public static void test(int... i) {
        for (int x : i) {
            System.out.println(x);
        }
}

递归

  • A方法调用A方法, 自己调用自己
  • 包括: 滴归头 和 递归体
  • 递归头: 什么时候不调用
  • 递归体: 什么时候需要调用
public static int f(int n) {
    if(n == 1){
        return 1;
    }else {
        return n*f(n-1);
    }
}</pre>
  • 相同类型数据的有序集合

声明数组

数据类型[] 数组名;
//或
数据类型 数组名[];
//动态初始化 (默认初始化)

数据类型[] 数组名 = new 数据类型[数组大小];

int[] arr = new int[10];
//静态初始化

int[] a = {1,2,3};
arr[0]

arr.length
//数组本身在堆中

特点

  • 长度固定
  • 元素类型相同
  • 数组本身是对象在堆中

数组的使用

  • 遍历循环
int[] arr = {1,2,3,4,5};
for(int i = 0; i < arr.length; i++){
    System.out.println(arr[i]);
}
for(int x : arr){

System.out.println(x);

}
  • 数组可以作为参数
public static void printArray(int[] arr){
    for(int x : arr){
    	System.out.println(x);
	}
}
  • 数据作为返回值
public static int[] recerse(int[] arr){
    int[] result = new int[arr.length];
    for(int i = 0; i < arr.length; i++){
    	result[(arr.length)-i -1] = arr[i];
	}
    return result;
}

二维数组

int[][] arr = new int[3][2];
int[][] a = {{2,3},{3,4},{6,5}};
a.length

a[0].length

Arrays类

int a = {1,4,5,6,7};
//打印
Arrays.toString(a);
//排序 升序
Arrays.sort();
//填充 将指定值填充数组
Arrays.fill(a,0);

冒泡排序

  • 比较相邻的数, 交换
  • 每次都会出一个最大或最小
  • 下轮循环少一次排序
int[] sort = sort(a);
    System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array){
    int temp =0;
    for(int i = 0; i < array.length-1; i++){
        for (int j =0; j < array.length-1-i; j++){
            if(array[j+1]>array[j]){
                temp = array[j];
                array[j] = array[j+1];
                array[j+1] = temp;
            }
        }
    }
    return array;
}</pre>
  • 当数组中大部分元素为0,或相同的值时, 使用稀疏数组
  • 处理方式:
  • 记录数据一共几行几列, 有多少个不同值
  • 把不同的值的元素和行列记录在一个小的数组中
System.out.println("=========原数组========");

    for (int[] ints : array1) {
        for (int anInt : ints) {
            System.out.print(anInt + "\t");
        }
        System.out.println();
    }

    //转化
    //获取个数
    int sum = 0;
    for (int i = 0; i < array1.length; i++) {
        for (int j = 0; j < array1[i].length; j++) {
            if (array1[i][j] != 0) {
                sum++;
            }
        }
    }

    //创建稀疏数组
    int[][] array2 = new int[sum + 1][3];
    array2[0][0] = array1.length;
    array2[0][1] = array1.length;
    array2[0][2] = sum;

    //存放非零数值
    int count = 0;
    for (int i = 0; i < array1.length; i++) {
        for (int j = 0; j < array1[i].length; j++) {
            if (array1[i][j] != 0) {
                count++;
                array2[count][0] = i;
                array2[count][1] = j;
                array2[count][2] = array1[i][j];
            }
        }
    }
    System.out.println("=========稀疏数组========");
    for (int[] ints : array2) {
        for (int anInt : ints) {
            System.out.print(anInt + "\t");
        }
        System.out.println();
    }

    System.out.println("=========还原数组========");

    int[][] array3 = new int[array2[0][0]][array2[0][1]];

    for (int i = 1; i < array2.length; i++) {
        array3[array2[i][0]][array2[i][1]] = array2[i][2];
    }

    for (int[] ints : array3) {
        for (int anInt : ints) {
            System.out.print(anInt + "\t");
        }
        System.out.println();
    }

}

 

内存分析

# 存放new的对象和数组
# 可以被所有的线程共享, 不会存放别的对象引用

# 存放基本变量类型 (会包含这个基本类型的具体数值)
# 引用对象的变量 (会存放这个引用在堆里面的具体地址)
# 方法

方法区

# 可以被所有的线程共享
# 包含了所有的class和static变量

面向对象

  • 以类的方式组织代码, 以对象的方式组织(封装)数据

类和对象的关系

  • 类是对象的模板
  • 对象是类的具体实例
// 创建对象时默认初始化 和 调用 构造器

构造器

// 和类名相同
// 没有返回值
// 定义了自己的有参构造, 无参构造需要手动定义

封装

// 数据封装, 统一接口方法
// 属性私有, 提供get/set  
// 隐藏代码实现细节
// 提高程序的安全性, 保护数据
// 增加程序可维护性

继承

  • 扩展
// extends
// 只有单继承
// 子类继承父类 公有的属性和方法
// 超类 Object

Super

// super: 调用父类公有的
// this: 当前类
// 子类构造器会 默认调用父类的构造器

// super()和this() 必须在子类构造器的第一行

// super() 和 this() 不同时出现
// 父类没有无参构造, 子类也不能有无参构造

方法重写

  • 对父类方法扩展
// 重写父类的的方法
// 不能重写私有的方法
// 子类修饰符可以扩大 但不能缩小
// 抛出的异常可以缩小 但不能扩大

多态

// 父类的引用指向子类对象
// 方法的调用只和右边new的谁有关 子类没有找父类

instanceof

// 有上下关系 才可以比较 同级不能比较

类型转换

// 高 转 低 ----> 强转  向下转型
Person obj = new Student();
Student stu = (Student)obj;
//低 转 高     向上转型   会丢失一些方法

Student student = new Student();

Person person = student;

static

// 静态的变量和方法 在静态方法区
// 静态变量和方法 可以通过 类名调用
// 被共享
// 跟着类的加载被加载
// 静态代码块: 初始化数据
// 匿名代码块 也会随着对象的创建被创建 在构造器之后  可以用于 初始赋值
// final 关键字: 最终

抽象类

// abstract 用于修饰 类 和 方法 
// 抽象类不能被实例化 但是抽象类是有构造方法的
// 抽象方法 必须 在抽象类中, 抽象类中可以 有 普通方法
// 继承抽象类的子类必须重写父类的所有抽象方法 除了子类也是抽象类

接口

  • 契约
// interface
// 接口的方法 默认 修饰 public abstract
// 接口都需要有实现类(重写接口的方法)
// 接口中的常量:  默认修饰 public static final
// 接口不能被实例化, 但是有构造方法

内部类

成员内部类

public class Outer {
    private int id;
    public void  out(){
        System.out.println("这是外部类的方法");
    }
    public class Inner {
        public void in(){
            System.out.println("这是内部类方法");
        }
    }
}
public class Test {

public static void main(String[] args) {

Outer outer = new Outer();

outer.out();

Outer.Inner in = outer.new Inner();

in.in();

}

}

静态内部类

// 在成员内部类上加上static

局部内部类

}
   }

匿名内部类

// 没有名字的内部类

异常机制

  • Exception
  • Error不是异常, 虚拟机错误
  • 运行时异常:
  • 数组下标越界
  • 空指针异常
  • 算术异常
  • 丢失资源
  • 找不到类

异常抛出和捕获

try{
}catch(Exception e){

e.printStackTrace();//打印错误信息

}finally{
}
throws new Exception
//finally 都会执行

//多个异常 从小到大

自定义异常类

//detail>10 异常
private int detail;

public MyException(int a){
    this.detail = a;
}  

@Override
public String toString(){
    return "MyException{" +
            "detail=" + detail + 
            "}";
}

static void test(int a) throws MyException{
    System.out.println("传递的参数是: " + a);
    if(a>10){
        throw new MyException(a);
    }
    System.out.println("OK");
}

public static void main(String[] args) {
    try {
        test(11);
    } catch (MyException e) {
        e.printStackTrace();
    }
}

权限修饰符

  • public > protected > (default) > private
  • default不是关键字

 

public

protected

default

private

同一个类

yes

yes

yes

yes

同一个包

yes

yes

yes

 

不同包子类

yes

yes

 

 

不同包非子类

yes

 

 

 

数组与排序

  • 注意二维数组:
int[][] arr
int arr[][]
int[] arr[]
int[] g,z[] : 表示一个一位数组, 一个二维数组

基础查找

private static int getIndexByEle(int[] arr, int ele) {
    for (int i = 0; i < arr.length; i++) {
        if(ele == arr[i]){
            return i;
        }
    }
    return -1;
}

二分查找(数组必须有序)

private static int getIndexByEle(int[] arr, int ele) {
    //定义最小索引 最大索引 中间索引
    int minIndex = 0;
    int maxIndex = arr.length - 1;
    int centerIndex = (minIndex + maxIndex) / 2;

    while (minIndex <= maxIndex) {

        if (ele == arr[centerIndex]) {
            return centerIndex;
        } else if (ele > arr[centerIndex]) {
            minIndex = centerIndex + 1;
        } else if (ele < arr[centerIndex]) {
            maxIndex = centerIndex - 1;
        }

        centerIndex = (minIndex + maxIndex) / 2;
    }

    return -1;
}

排序算法

冒泡排序

  • 相邻元素两两比较, 比较大或小, 一轮得到最大值或最小值 一轮后 减少一次比较
System.out.println(Arrays.toString(arr));
    System.out.println("交换次数: " + swapCount);
}

选择排序

  • 将第0个元素 一次和后面的比较, 得到最小值或最大值 在第一个位置
public class Test {
    public static void main(String[] args) {
        int[] arr = {24, 69, 80, 57, 13};
        for (int index = 0; index < arr.length - 1; index++) {
            for (int i = index + 1; i < arr.length; i++) {
                if (arr[index] > arr[i]) {
                    int temp = arr[index];
                    arr[index] = arr[i];
                    arr[i] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

插入排序

  • 将元素插入到一个有序的列表中, 保持有序
System.out.println(Arrays.toString(arr));
}

    System.out.println(Arrays.toString(arr));
}

希尔排序

  • 缩小增量排序: 对直接插入排序的优化
  • 指定增量 为间隔 , 根据间隔进行比较 当间隔为1时 完成排序
  • 通过不断缩小增量, 每轮达到大致有序
shellSort(arr);

    System.out.println(Arrays.toString(arr));
}

private static void shellSort(int[] arr) {
    //定义增量 h
    // 可以选取数组的一半
    // 在优化: 通过克努特序列
        //增量选取 int h = 1;  h = h*3+1   ---> 1,4,13,40,121,364
    // 算出h
    int jiange = 1;
    while(jiange <= arr.length/3){
        jiange = jiange * 3 + 1;
    }
    System.out.println(jiange);
    for (int h = jiange; h > 0; h = (h-1)/3) {
        for (int i = h; i < arr.length; i++) {
            for (int j = i; j > h - 1; j -= h) {
                if (arr[j] < arr[j - h]) {
                    int temp = arr[j];
                    arr[j] = arr[j - h];
                    arr[j - h] = temp;
                }
            }
        }
    }
}

快速排序

  • 总体分区法
  • 选择一个元素作为基准: 比该元素大的放一边, 小的放一边
  • 过程挖坑填数法
  •  
/*
一组元素中,  将第一个位置作为第一个坑位1, 记录基准数 从右边找比基准数 小的数作为坑位2, 将坑位2的数放到坑位1,  在从左边开始找比基准数 大的数作为坑位3 把坑位3 的数放到坑位2, 在从右边找比基准数小的数作为坑位4 把坑位4的数 放到坑位3 依次类推 
直到 找完 后 两边的数 就变为 大于基准数的在一边, 小于基准数的在一边
在对两边进行同样的操作
*/
quickSort(arr, 0, arr.length-1);

    System.out.println(Arrays.toString(arr));
}

private static void quickSort(int[] arr, int start, int end) {
    //找出分左右恋曲的索引位置, 然后对左右两边进行递归调用
    if (start < end){
        int index = getIndex(arr,start,end);
        quickSort(arr,start,index-1);
        quickSort(arr,index+1,end);
    }
}

private static int getIndex(int[] arr, int start, int end) {
    int i = start;
    int j = end;
    int x = arr[i];

    while (i<j){
        //由后向前找比他小的数, 找到后挖出此数填到前一个坑
        while (i<j && arr[j] >= x){
            j--;
        }
        if(i<j){
            arr[i]=arr[j];
            i++;
        }

    }
    arr[i] = x;// 把基准数放到最后的位置
    return i;
}

归并排序

  • n个元素的序列, 看成是由n个1个元素的序列组成
//归并
    //guiBing(arr,0,3,arr.length-1);

    System.out.println(Arrays.toString(arr));
}

private static void chaifen(int[] arr, int startIndex, int ednIndex) {
    //计算中间索引
    int centerIndex = (startIndex+ednIndex)/2;
    if (startIndex<ednIndex){
        chaifen(arr,startIndex,centerIndex);
        chaifen(arr,centerIndex+1,ednIndex);
        guiBing(arr,startIndex,centerIndex,ednIndex);
    }
}

private static void guiBing(int[] arr, int startIndex, int centerIndex, int endIndex) {
    //定义临时数组
    int[] tempArr = new int[endIndex-startIndex+1];
    //定义左边数组的起始索引
    int i = startIndex;
    //定义右边数组的起始索引
    int j = centerIndex + 1;
    //定义临时数组起始索引
    int index = 0;
    //比较左右两个数组的元素大小, 往临时数组中放
    while(i<=centerIndex&&j<=endIndex){
     if(arr[i]<=arr[j]){
         tempArr[index] = arr[i];
         i++;
     }else {
         tempArr[index] = arr[j];
         j++;
     }
     index++;
    }
    //处理剩余元素
    while (i<=centerIndex){
        tempArr[index]=arr[i];
        i++;
        index++;
    }
    while (j<=endIndex){
        tempArr[index]=arr[j];
        j++;
        index++;
    }

    //将临时数组中的元素替换原数组
    for (int k = 0; k <tempArr.length ; k++) {
        arr[k+startIndex] = tempArr[k];
    }
}

基数排序

  • 分配在收集
sortArray(arr);

    System.out.println(Arrays.toString(arr));
}

private static void sortArray(int[] arr) {
    //定义存放的数组
    int[][] tempArr = new int[10][arr.length];
    //定义统计数组
    int[] counts = new int[10];
    //获取数组中的最大值
    int max = getMax(arr);
    //得确定排序轮次
    int len = String.valueOf(max).length();
    //循环次数
    for (int i = 0, n=1; i < len; i++, n*=10) {
        for (int j = 0; j < arr.length; j++) {
            // 获取每个位置上的数组
            int ys = arr[j]/n%10;
            tempArr[ys][counts[ys]++]=arr[j];
        }
        //取出桶中的元素
        int index = 0;
        for (int k = 0; k < counts.length; k++) {
            if(counts[k]!=0){
                for (int h = 0; h < counts[k]; h++) {
                    arr[index] = tempArr[k][h];
                    index++;
                }
                counts[k]=0;//清除上一次桶中的数
            }
        }
    }
}

private static int getMax(int[] arr) {
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if(arr[i] > max){
            max = arr[i];
        }
    }
    return max;
}

堆排序

  • 大顶堆 升序
  • 小顶堆 降序
  • 二叉树
private static void toMaxHeap(int[] arr, int size, int index) {
    //获取左右子节点的索引
    int leftNodeIndex = index * 2 + 1;
    int rightNodeIndex = index * 2 + 2;
    //查找最大节点所对应的索引
    int maxIndex = index;
    if(leftNodeIndex<size && arr[leftNodeIndex]>arr[maxIndex]){
        maxIndex = leftNodeIndex;
    }
    if(rightNodeIndex<size && arr[rightNodeIndex]>arr[maxIndex]){
        maxIndex = rightNodeIndex;
    }
    //交换位置
    if(maxIndex!=index){
        int temp = arr[maxIndex];
        arr[maxIndex] = arr[index];
        arr[index] = temp;
        // 影响子树
        toMaxHeap(arr, size, maxIndex);
    }
}

常用类

Object

  • boolean equals (Object obj)
  • String toString()
*/
    System.out.println(person.toString());
    //Person{name='jack', age=18}
}
package com.cyz.demo05;

public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("jack",18);
        Person p2 = new Person("mark",18);

        boolean flag = p1.equals(p2);
        System.out.println(flag);//false

        /*
             public boolean equals(Object obj) {
                return (this == obj);
            }
            // this -> p1
            // obj -> obj
            // == 比较地址值
         */

        Person p3 = new Person("mark",18);

        // Person 重写 equals 方法
        /*
            @Override
            public boolean equals(Object obj) {
                if(obj== this){
                    return true;
                }
                if(obj == null){
                    return false;
                }
                if (obj instanceof Person){
                    Person p = (Person)obj;
                    boolean b = this.name.equals(p.name) && this.age == p.age;
                    return b;
                }

                return false;

            }
         */

        System.out.println(p2.equals(p3));
    }

}
@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        //使用反射
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

Objects类

  • equals
//解决空指针异常 
public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
 }

哈希值

// 是一个十进制的整数, 由系统随机给出(地址值, 逻辑地址, 非真实物理地址)
// 获取哈希值: hashcode()

hashcode()

Person p2 = new Person();
    int h2 = p2.hashCode();
    System.out.println(h2);//1163157884
    
    //Person未重写hashCode 使用的是Object的hashcode
}

 

clone()

getClass()

notify()

// 唤醒单个线程

wait()

// 和sleep 一样

 

System

  • currentTimeMillis() 获取系统当前时间毫秒数 一般用于测试程序执行时间
  • arraycopy(源数组, 起始位置, 目标数组,, 目标数据中的起始位置, 要复制的数组元素的数量)
int[] arr = {1,2,3,4,5};

    int[] arr2 = {6,7,8,9,10};
    System.arraycopy(arr,0,arr2,0,3);
    System.out.println(Arrays.toString(arr));
    System.out.println(Arrays.toString(arr2));
}

 

Math类

  • double abs(double num) 绝对值
  • double ceil(double num) 向上取整
  • double floor(double num) 向下取整
  • long round(double num) 四舍五入
  • double pow(double a, double b) a 的 b 次方
public class Test {
    public static void main(String[] args) {
       System.out.println(Math.abs(-2));//2
       System.out.println(Math.ceil(3.4));//4.0
       System.out.println(Math.floor(3.9));//3.0
       System.out.println(Math.round(3.6));//4
       System.out.println(Math.pow(2,3));//8.0
    }
}

Random

System.out.println(random.nextInt(10));//范围在 [0,10)

    System.out.println(random.nextInt(10)+1);//范围在 [1,11) 也就是[1,10]
}

UUID

String str = UUID.randomUUID().toString();
System.out.println(str.replaceAll("-",""));//32位
//17257a500fc84a95ba24bc5bbdc71103

File

创建文件

查看文件

修改文件

删除文件

包装类

基本类型

包装类

byte

Byte

short

Short

int

Integer

long

Long

char

Character

float

Float

double

Double

boolean

Boolean

Integer in4 = Integer.valueOf("2");
    System.out.println(in4);

}

自动拆箱和装箱 jdk1.5+

// 自动装箱
Integer in = 1;
// 自动拆箱 + 自动装箱

in = in + 2;

基本类型&String相互转换

// 直接 + ""
// 使用parseInt 处理char其他都有对应

Date类

  • 毫秒值: 1000ms = 1s
  • 0毫秒 1970年1月1日 0时0分0秒
  • 获取系统时间: System.currentTimeMillis()
  • 在中国 获取的是 到1970年1月1日 8时0分0秒 东八区

Date

date = new Date(0L);
    System.out.println(date);//Thu Jan 01 08:00:00 CST 1970

    date = new Date(1594544955624L);
    System.out.println(date);//Sun Jul 12 17:09:15 CST 2020

    //转为毫秒值
    System.out.println(date.getTime());//1594544955624
}

SimpleDateFormat

  • format 格式化
  • parse 格式化转回
String str = sdf.format(date);
    System.out.println(str);//2020-07-12 17:20:55

    // 将指定格式的字符串解析为 Date对象
    try {
        Date date2 = sdf.parse("2020-07-12 17:20:55");
        System.out.println(date2);//Sun Jul 12 17:20:55 CST 2020
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

Calendar

*/

    //获取
    int year = c.get(Calendar.YEAR);//2020
    System.out.println(year);
    int month = c.get(Calendar.MONTH);//6
    System.out.println(month);
    int data = c.get(Calendar.DATE);//12
    System.out.println(data);

    System.out.println(c.get(Calendar.DAY_OF_MONTH));//12


    //设置
    c.set(Calendar.YEAR,9999);
    year = c.get(Calendar.YEAR);//9999
    System.out.println(year);

    c.set(Calendar.MONTH,9);
    month = c.get(Calendar.MONTH);//9
    System.out.println(month);

    c.set(Calendar.DATE,9);
    data = c.get(Calendar.DATE);//9
    System.out.println(data);

    //同时设置年月日
    c.set(8888,8,8);
    year = c.get(Calendar.YEAR);//8888
    System.out.println(year);

    month = c.get(Calendar.MONTH);//8
    System.out.println(month);

    data = c.get(Calendar.DATE);//8
    System.out.println(data);

    c.add(Calendar.YEAR,2);
    c.add(Calendar.MONTH,-1);
    c.add(Calendar.DATE,-1);

    year = c.get(Calendar.YEAR);//8890
    System.out.println(year);

    month = c.get(Calendar.MONTH);//7
    System.out.println(month);

    data = c.get(Calendar.DATE);//7
    System.out.println(data);

    //将日历对象转换为 日期对象
    Date time = c.getTime();
    System.out.println(time);
    // Mon Aug 07 17:41:08 CST 8890
}

String类

  • 不可变性
// 字面量 "abc" 都是String 的实例对象  共享使用
// 底层是byte[]字节数组

三种构造方法

String()
String(char[] array) // 底层还是会先创建byte数组
String(byte[] array)
char[] chars = {'a','b'};
    String str2 = new String(chars);
    System.out.println(str2);

    byte[] byres = {98,99};
    String str3 = new String(byres);
    System.out.println(str3);


    String str4 = new String("aaa");
    System.out.println(str4);

    //直接创建 也是对象
    String str5 = "ccc";
    System.out.println(str5);

    /*
        第一个字符串为:
        ab
        bc
        aaa
        ccc
     */
}

常量池

  • 字符串直接使用""双引号创建的就在常量池中
  • 常量池中保存的是字节数组的地址值
char[] chars = {'a','b','c'};
    String str3 = new String(chars);

    System.out.println(str1 == str2);
    System.out.println(str1 == str3);
    System.out.println(str2 == str3);
    
    System.out.println(str1.equals(str2));
    System.out.println(str1.equals(str3));
    System.out.println(str2.equals(str3));
    /*
        true
        false
        false
        
        true
        true
        true
        
        ==比较的是地址值
        equals比较的是值
     */
}

常用方法

  • boolean equals(String str) : 比较的字符串的内容
  • 常量写左边
  • boolean equalsIgnoreCase(String str) : 忽略大小写比较
  •  
  • int length(): 字符串长度
  • String concat(String str) 字符串拼接
  • char charAt(int index);: 获取指定位置的单个字符
  • int indexOf(String str): 查找字符串在首次出现的位置, 没有返回-1
  • Sttring substring(int index) 截取指定位置开始到最后的字符串
  • Sttring substring(int begin, int end) 截取 [begin,end) 到最后的字符串
  •  
  • char[] toCharArray() 将字符串拆分成字符数组
  • byte[] getBytes() 获取字符串底层byte[]数组
  • String replace(CharSequence oldString, CharSequence newString) 将出现的老字符替换为新字符
  •  
  • String[] split(String regex) 按照参数规则 分割字符串
  • 注意是正则
  • 特殊需要转义
char[] chars = {'a','b','c'};
    String str3 = new String(chars);

    System.out.println(str1.equals(str2));
    System.out.println(str1.equals(str3));
    System.out.println(str2.equals(str3));
    /*
        true
        true
        true
     */
}
public class Test {
    public static void main(String[] args) {
        String str1 = "abc";
        String str4 = null;
        System.out.println(str1.equals(str4));
        System.out.println(str4.equals(str1));
        /*
            false
            //NullPointerException 空指针异常
         */
    }
}
public class Test {
    public static void main(String[] args) {
        int length = "sadasdasdasdasdasd".length();//18
        System.out.println(length);

        String str1 = "hello";
        String str2 = "World";
        String str3 = str1.concat(str2);
        System.out.println(str1);//hello
        System.out.println(str2);//World
        System.out.println(str3);//helloWorld

        char c = "Hello".charAt(1);//e
        System.out.println(c);

        String str4 = "helloWorld";
        int index = str4.indexOf("llo");//2
        System.out.println(index);
        int index2 = str4.indexOf("c");
        System.out.println(index2);//-1

        String str5 = str4.substring(5);
        System.out.println(str5);//World

        String str6 = str4.substring(0,5);
        System.out.println(str6);//hello

        System.out.println(str4);//helloWorld
    }
}
public class Test {
    public static void main(String[] args) {
        char[] chars = "Hello".toCharArray();
        System.out.println(chars[0]);//H
        System.out.println(chars.length);//5

        byte[] bytes = "abc".getBytes();
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
            /*
                97
                98
                99
             */
        }

        String str1 = "How do you do?";
        String o = str1.replace("o", "*");
        System.out.println(o);//H*w d* y*u d*?

    }
}
public class Test {
    public static void main(String[] args) {
       String str1 = "aaa,bbb,ccc";
       String[] arr = str1.split(",");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
            /*
                aaa
                bbb
                ccc
             */
        }
       String str2 = "aaa.bbb.ccc";
       String[] arr = str2.split("\\.");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
            /*
                aaa
                bbb
                ccc
             */
        }
    }
}

StringBuffer

  • 可变长
  • append
  • 多线程数据量较大
  • 效率低, 线程安全

StringBuilder

  • 字符串缓冲区
  • 可变长
  • 单线程数据量较大
  • 效率高, 线程不安全
  • 底层也是btye[] 数组 但没有被final修饰, 是可变的
  • 在内存中始终是一个数组, 超过容量自动扩容
// String 进行相加  中间创建太多的字符串对象, 效率低
// "a" + "b" + "c"
StringBuilder bu2 = new StringBuilder("abc");
    System.out.println("bu2: "+bu2);
    /*
        bu1:
        bu2: abc
     */

    // 由于返回的是this 可以链式调用
    bu3.append(2).append("sss").append("sdd");
    System.out.println("bu3: "+bu3);//bu3: aaa1true0.0中2ssssdd
}

 

Arrays

  • String toString(数组) 数组变为字符串 [元素1, 元素2, ....]
  • void sort(数组) 升序排序
  • 数字和字母升序
  • 自定义类型 需要实现Comparable 或 Comparator
StringBuilder bu2 = new StringBuilder("abc");
    System.out.println("bu2: "+bu2);
    /*
        bu1:
        bu2: abc
     */

    // 由于返回的是this 可以链式调用
    bu3.append(2).append("sss").append("sdd");
    System.out.println("bu3: "+bu3);//bu3: aaa1true0.0中2ssssdd

    //反转
    bu3.reverse();
    System.out.println("bu3: "+bu3);//bu3: ddssss2中0.0eurt1aaa
}
package com.cyz.demo05;

public class Test {
    public static void main(String[] args) {
        String str = "hello";
        System.out.println("str: " + str);
        StringBuilder bu = new StringBuilder(str);
        bu.append("a").append(1).append(true);
        System.out.println("bu: " + bu);

        String s = bu.toString();
        System.out.println("s: " + s);
        /*
            str: hello
            bu: helloa1true
            s: helloa1true
         */
    }
}

数据结构

// 入口和出口 在集合同一侧
// 入栈或压栈
// 出栈或弹栈
// 先进后出

队列

// 入口和出口 在集合的两侧
// 先进先出

数组

// 查询快:  数组地址是连续的, 根据首地址可以查询到数组, 根据索引可以定位到数据
// 增删慢: 长度不可变, 改变需要创建新数组, 拷贝原数组, 重新赋值	
// 	重复复制, 销毁原数组, 效率低

链表

// 查询慢: 链表地址不是连续的, 每次查询必须从头开始
// 增删快: 增删对链表结构没有影响 只用把节点地址更改即可
// 每一个元素称为 节点
// 节点: 数组源(存数组) + 两个指针域(存地址)
//	自己的地址 + 数据 + 下一个节点的地址
//分类:

// 单向链表: 只有一条链, 不能保证元素的顺序(存和取的元素顺序可能不一致)

// 双向链表: 两条链, 一条链专门记录元素的顺序, 是一个有序的集合

红黑树

二叉树

  • 分支不能超过两个
//	           *
//左子树	*        *//右子树
//树叶   *   *     *  *

排序树/查找树

  • 在二叉树的基础上, 元素有大小顺序
  • 左子树小, 右子树大
  • 查询速度快

*衡树

  • 左子树的数量 等于 右子树的数量
  • 查询速度快

不*很树

  • 左子树的数量 不等于 右子树的数量
*
     *		*
   *   *
 *

红黑树

  • 趋*于*衡树
  • 查询速度快, 查询子节点最大次数和最小次数不能超过2倍
  • 约束:
  • 节点可以是黑色的也可以是红色的
  • 根节点是黑色的
  • 叶子节点(空节点)是黑色的
  • 每个红色的节点的子节点颜色都是黑色的
  • 任何一个节点到其叶子节点的所有路径上的黑色节点数相同

Collection

  • 长度可变, 存对象,类型可以不同
boolean flag = coll.add("a");
    System.out.println(flag);//true
    System.out.println(coll);//[a]

    coll.add("b");
    coll.add("c");
    System.out.println(coll);//[a, b, c]

    System.out.println(coll.size());//3

    boolean flag1 = coll.remove("a");
    System.out.println(flag1);//true
    boolean flag2 = coll.remove("a");
    System.out.println(flag2);//false

    boolean flag3 = coll.contains("a");
    System.out.println(flag3);//false

    boolean flag4 = coll.isEmpty();
    System.out.println(flag4);//false

    Object[] arr = coll.toArray();
    System.out.println(Arrays.toString(arr));//[b, c]

    coll.clear();
    System.out.println(coll.size());//0
    System.out.println(coll.isEmpty());//true
}

Iterator

Iterator<String> it =coll.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
            /*
                b
                c
             */
        }
# 实现原理
 Iterator<String> it =coll.iterator(); # 获取迭代对象
 it.hasNext() # 判断是否有下一位
 it.next() # 取出元素 指针向后移动
// 增强for循环底层实现是迭代器
for (String str : coll){
            System.out.println(str);
            /*
                b
                c
             */
        }

 

List

  • 有序可重复, 有索引
System.out.println(list);//[a, b, c, d, a] 有序, 可重复

    list.add(3, "chen"); //添加指定位置
    System.out.println(list);//[a, b, c, chen, d, a]

    String removeE = list.remove(2);
    System.out.println("移除的是: " + removeE);//移除的是: c
    System.out.println(list);//[a, b, chen, d, a]

    String setE = list.set(4, "A");
    System.out.println("被替换的元素: " + setE);//被替换的元素: a
    System.out.println(list);//[a, b, chen, d, A]

    //遍历
    for (int i = 0; i < list.size(); i++) {
        String s = list.get(i);
        System.out.println(s);
    }

    Iterator it = list.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }

    for (String s : list) {
        System.out.println(s);
    }
}

 

ArrayList: 底层是数组 查询快 增删慢
  • 不同步的, 多线程
  • add
  • get
  • remove
  • contains
  • size
for (int i = 0; i < list.size(); i++){
        System.out.println(list.get(i));
    }
    /*
        [100, 200]
        200
        100
        200
     */
}
package com.cyz.demo05;

import java.util.ArrayList;
import java.util.Random;

public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();

        Person p1 = new Person("one",1);
        Person p2 = new Person("two",2);
        Person p3 = new Person("three",3);
        Person p4 = new Person("four",4);

        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);

        for (int i = 0; i < list.size(); i++){
            Person person = list.get(i);
            System.out.println(person.getName());
        }

        /*
            one
            two
            three
            four
         */
    }
}
package com.cyz.demo05;

import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("abc");
        list.add("cde");
        list.add("asd");

        System.out.println(list.contains("a"));//false
        System.out.println(list.contains("abc"));//true
        list.remove("abc");
        System.out.println(list.contains("abc"));//false
        list.remove(1);

        for (int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));//cde
        }
    }
}
LinkedList: 链表实现 查询慢 增删快
  • 不能使用多态创建
  • getFirst()
  • getLast()
  • removeFirst()
  • removeLast();
  • addFirst()//push()
  • addLast()//pop()
private static void show03() {
    LinkedList<String> linked = new LinkedList<>();
    linked.add("a");
    linked.add("b");
    linked.add("c");
    System.out.println(linked);//[a, b, c]

    String first = linked.removeFirst();

    String last = linked.removeLast();
    System.out.println("移除的元素: " + last);//移除的元素: c
    System.out.println(linked);//[b]
}

private static void show02() {
    LinkedList<String> linked = new LinkedList<>();
    linked.add("a");
    linked.add("b");
    linked.add("c");
    System.out.println(linked);//[a, b, c]

    if (!linked.isEmpty()) { //判断是否为空
        String first = linked.getFirst();
        System.out.println(first);//a

        String last = linked.getLast();
        System.out.println(last);//c
    }

    linked.clear();//清空
}

private static void show01() {
    // 创建不能使用多态
    LinkedList<String> linked = new LinkedList<>();
    linked.add("a");
    linked.add("b");
    linked.add("c");
    System.out.println(linked);//[a, b, c]

    linked.addFirst("w");

    linked.addLast("n");
    System.out.println(linked);//[w, a, b, c, n]
}
Vector
  • 单例集合的鼻祖
  • 底层也是数组, 同步的, 单线程 实现可增长的数组
  • 实现 List
  • elements遍历
  • hasMoreElements()
  • nextElement()
Stack
  • 继承Vector

Set

  • 无序不可重复
  • 继承Collection 无序没有索引
HashSet: 底层哈希表 + 红叉树 无索引 不可重复 获取无序 多线程, 不同步
  • 哈希表结构: 查询速度快
Iterator<Integer> it = set.iterator();
    while (it.hasNext()) {
        Integer n = it.next();
        System.out.println(n);
    }
}
  • 存储数据结构(哈希表)
//1.8之前: 哈希表: 数组 + 链表;
//1.8之后: 哈希表: 数组 + 红黑树(提高查询速度)
// 哈希表特点: 查询速度快
//数组结构: 把元素进行分组,(相同哈希值的元素一组)  存的哈希值

//链表/红黑树结构: 连接哈希值相同的元素
//在1.8之后如果链表长度超过8位就会转为红黑树
//存数据的到集合中 先计算元素的哈希值
  • 不重复的原理
// 调用add() 时会调用 hashCode方法 计算哈希值
// 查看集合中是否有相同哈希值的元素
// 有的话 通过equals() 比较 如果返回false 则存入
//存储的元素必须重写hashCode和equals方法
LinkedHashSet
  • 底层哈希表 + 链表 无索引 不可重复, 获取有序
LinkedHashSet<String> linked = new LinkedHashSet<>();
    linked.add(s1);
    linked.add(s2);
    linked.add("d");
    linked.add("c");
    linked.add("abc");
    System.out.println(linked);//[abc, d, c]
}

 

  • LinkedHashSet 底层哈希表 + 链表 无索引 不可重复, 获取有序
     
TreeSet: 底层二叉树 一般用于排序

Map

  • 键值对 key不允许重复
  • 数据类型可以不同

HashMap

  • 无序, 存和取的顺序可能不一致
  • 底层是哈希表
    哈希表:
  • jdk1.7 数组 + 链表(单向链表)
  • jdk1.8 hash表 = 数组+ 链表 +红黑树
private static void show02() {
    //key和value数据类型不同
    Map<String,Integer> map = new HashMap<>();
    map.put("a",1);
    map.put("b",2);
    map.put("c",3);
    map.put("d",4);
    System.out.println(map);//{a=1, b=2, c=3, d=4}

    Integer a = map.remove("a");
    System.out.println(a);//1

    Integer e = map.remove("e");
    System.out.println(e);//null

    System.out.println(map);//{b=2, c=3, d=4}
}

private static void show01() {
    // key相同时为 替换
    Map<String,String> map = new HashMap<>();
    String a = map.put("1", "a");
    System.out.println(a);//null
    String b = map.put("1", "b");
    System.out.println(b);//a
    System.out.println(map);//{1=b}

    map.put("2","c");
    map.put("3","d");
    map.put("4","3");
    System.out.println(map);//{1=b, 2=c, 3=d, 4=3}

    String s = map.get("1");
    System.out.println(s);//b
    boolean b1 = map.containsKey("1");
    System.out.println(b1);//true

    String s2 = map.get("5");
    System.out.println(s2);//null
    boolean b2 = map.containsKey("5");
    System.out.println(b2);//false

}
public class Test {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        map.put("d", 4);
        // Set<K> keySet() 把Map集合的所有ket取出来存到Set中
        // Set 可以使用迭代器 或 增强for
        Set<String> set = map.keySet();
        for (String s : set) {
            System.out.println(s + "=" + map.get(s));
        }
        /*
            a=1
            b=2
            c=3
            d=4
         */
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = it.next();
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
         /*
            a=1
            b=2
            c=3
            d=4
         */
    }
}
public class Test {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        map.put("d", 4);
//        Map.Entry<K,V>: 存放键值对   Map集合一创建就存在
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
        while (it.hasNext()) {
            Map.Entry<String, Integer> entry = it.next();
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        /*
            a=1
            b=2
            c=3
            d=4
         */
        for ( Map.Entry<String, Integer> entry : entrySet){
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
         /*
            a=1
            b=2
            c=3
            d=4
         */
    }
}
  • 使用自定义类型时, 需要重写 hashCode 和 equals 保证key唯一性
linkedHashMap
  • 哈希表 + 链表(记录元素顺序)
  • 有序
  • 存储元素和取出顺序元素一致
LinkedHashMap<String,Integer> linked = new LinkedHashMap<>();
    linked.put("a", 1);
    linked.put("c", 3);
    linked.put("b", 2);
    linked.put("d", 4);
    System.out.println(linked);//{a=1, c=3, b=2, d=4}
}
public class Test {
    public static void main(String[] args) {
//        Hashtable 单线程, 同步 线程安全的 速度慢  key和value不能为null 底层也是哈希表
        // 被HashMap取代
        HashMap<String, String> map = new HashMap<>();
        map.put(null,"a");
        map.put("b",null);
        map.put(null,null);
        System.out.println(map);//{null=null, b=null}

        Hashtable<String, String> mapt = new Hashtable<>();
//        mapt.put(null,"a");//NullPointerException
//        mapt.put("b",null);//NullPointerException
//        mapt.put(null,null);//NullPointerException
        mapt.put("a","b");
        System.out.println(mapt);//{a=b}

    }
}

TreeMap

集合优化方法 of jdk9新特性

List<String> list = List.of("a","b","c","d");
    System.out.println(list);

 

Collections工具类

  • <T><T> c, T... elements)
  • void shuffle()
  • <T><T> list)
  • <T><T> list, Comparator<? super T>)
ArrayList<Integer> list01 = new ArrayList<>();
    list01.add(1);
    list01.add(3);
    list01.add(2);
    System.out.println(list01);//[1, 3, 2]

    Collections.sort(list01);//默认升序
    System.out.println(list01);//[1, 2, 3]

    Collections.sort(list);
    System.out.println(list);//[a, b, c, d]

    //对于自定义类 需要实现Comparable接口 中的 CompareTo 方法
    ArrayList<Person> list3 = new ArrayList<>();
    list3.add(new Person("1",18));
    list3.add(new Person("2",20));
    list3.add(new Person("1",15));
    System.out.println(list3);
    //[Person{name='1', age=18}, Person{name='2', age=20}, Person{name='1', age=15}]

    Collections.sort(list3);
    System.out.println(list3);
    //[Person{name='2', age=20}, Person{name='1', age=18}, Person{name='1', age=15}]

}

Comparable和Comparator的区别

//Comparable: 自己(this)和别人(参数)比较, 自己需要实现Comparable接口, 重写CompareTo()
//Comparator: 相当于找一个第三方的裁判, 比较两个
public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(2);
        System.out.println(list);//[1, 3, 2]

        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-o2;//升序
            }
        });

        System.out.println(list);//[1, 2, 3]
    }
}
public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("1",18));
        list.add(new Person("2",20));
        list.add(new Person("3",15));
        System.out.println(list);
        //[Person{name='1', age=18}, Person{name='2', age=20}, Person{name='3', age=15}]

        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();//升序
            }
        });

        System.out.println(list);
        //[Person{name='3', age=15}, Person{name='1', age=18}, Person{name='2', age=20}]
    }
}

 

泛型

  • 约束, 避免类型转换之间的问题
  • 泛型类型 作为参数类型使用
class ArrayList<String> {
    boolean add(String a){};
}
  • 可以使用在类, 方法, 接口
public <M> void method(M a){
}
  • 泛型通配符?
ArrayList<String> list1 = new ArrayList<>();
    list1.add("a");
    list1.add("b");

    ArrayList<Integer> list2 = new ArrayList<>();
    list2.add(1);
    list2.add(2);

    printArray(list2);
}

private static void printArray(ArrayList<?> list) {
    Iterator it =list.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}
  • 上限 ? extends E
  • 下限 ? super E

斗地主案例

//洗牌 shuffle
    Collections.shuffle(poker);

    // 发牌
    //定义玩家 + 底牌
    ArrayList<String> player01 = new ArrayList<>();
    ArrayList<String> player02 = new ArrayList<>();
    ArrayList<String> player03 = new ArrayList<>();
    ArrayList<String> diPai = new ArrayList<>();

    //遍历集合
    // i >=51 发底牌
    for (int i = 0; i < poker.size(); i++) {
        // 获取牌
        String p = poker.get(i);
        if(i>=51){
            diPai.add(p);
        }else if(i % 3 == 0){
            player01.add(p);
        }else if(i % 3 == 1){
            player02.add(p);
        }else if(i % 3 == 2){
            player03.add(p);
        }
    }

    //看牌
    System.out.println("p1: " + player01);
    System.out.println("p2: " + player02);
    System.out.println("p3: " + player03);
    System.out.println("dp: " + diPai);
}

 

IO流

字节流

输出OutputStream

输入InputStream

字符流

Reader

Writer

节点流

charArrayReader,Writer

inputstream

outputstream

StringReader, Writer

pipe(管道流)

PipedOutputStream

File(,,,)

处理流

buffer

bufferInputStream
bufferOutputStream
bufferReader
bufferWriter

序列化

反序列化 Serializable transient(透明的)

data

DataInputStream
DataOutputStream

转换流

InputStreamReader
OutputStreamWriter

过滤流Filter(四个)

print

PrintWriter
PrintStream

多线程

网络编程

IP

端口

Socket编程

TCP

三次握手

四次挥手

面向连接

UDP

无连接

Packet

URL

初始Tomcat

聊天通信

文件上传

GUI

AWT

Swing

注释和反射