Java语言学习1

发布时间 2023-06-28 09:58:13作者: wolaile1

JavaSE1

机器语言的发展史

第一代语言(机器语言)

  • 机器语言

    • 计算机的基本计算方式都是基于二进制的方式。
    • 二进制: 0101010010110101001
    • 这种代码是直接输入给计算机使用的,不经过任何转换

    1 01

    2 10

    3 11

    4 100

    5 101

    6 110

    7 111

    8 1000

    16 10000

    32 100000

第二代机器语言(汇编语言)

  • 汇编语言

    • 解决人类无法读懂机器语言的问题
    • 指令代替二进制
    codesg segment
      start:
      	mov ax, 0123h	; 寄存器送入值
      	mov bx, 0457h
      	add ax, bx		; ax + bx 寄存器值相加
      	add ax, ax		; 累加 ax
    
      mov ax, 4c00h
      int 21h				; 程序结束返回
    
    codesg ends
    end start				; 指定程序入口标号 start
    
  • 目前应用:

    • 逆向工程
    • 机器人
    • 病毒
    • .......

第三代语言(高级语言)

  • 摩尔定律
    • 当价格不变时,集成电路上容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上。(例子:现在能用过去同样的价格买到性能更好的电脑,现在用5000元买到电脑,比过去5000元买到的电脑性能更好)
  • 高级语言
  • 大体上分为:面向过程和面向对象两大类。
  • C语言是典型的面向过程的语言。C++, JAVA是典型的面向对象的语言。
  • 各种语言:
    • C语言
    • C++语言
    • JAVA语言
    • C#语言
    • Python、PHP、JavaScript
    • ......

Java入门

Java的诞生

C & C++

  • 1972年C诞生
    • 贴近硬件,运行极快,效率极高
    • 操作系统,编译器,数据库,网络系统等
    • 指针和内存管理
  • 1982年C++诞生
    • 面向对象
    • 兼容C
    • 图形领域、游戏等

Java初生

  • 1995年的网页简单而粗糙, 缺乏互动性。

  • Java语言编写的图形化的程序(Applet)

  • Java 2标准版(J2SE):桌面

  • Java 2移动版(J2ME):手机

  • Java 2企业版 (J2EE):服务器

Java发展

  • 基于Java开发了巨多的平台,系统,工具
    • 构建工具:Ant, Maven, Jekins
    • 应用服务器: Tomcat, Jetty, Jboss, Websphere, weblogic
    • Web开发:Struts, Spring, Hibernate, MyBatis
    • 开发工具:Eclipse, Netbean, intellij idea, Jbuilder
    • .......
  • 2006: Hadoop (大数据领域)
  • 2008: Android (手机端)

Java特性和优势

  • 简单性
  • 面向对象
  • 可移植性(跨平台)
  • 高性能
  • 分布式
  • 动态性
  • 多线程
  • 安全性
  • 健壮性

Java三大版本

  • Write once, Run Anywhere

  • Java2SE: 标准版(桌面开发,控制台开发.....)

  • JavaME:嵌入式开发(手机,小家电.....)

  • JavaEE:企业级开发(Web端, 服务器开发.....)

JDK 、JRE、JVM

  • JDK: Java Development Kit (java开发者工具)
  • JRE: Java Runtime Environment(java运行时环境)
  • JVM: JAVA Virtual Machine (java虚拟机)
  • img

HelloWorld

  1. 随便新建一个文件夹,存放代码
  2. 新建一个java文件
    • 文件后缀名为.java
    • HelloWorld.java
  3. 编写代码
public class HelloWorld{
	public static void main(String[] args){
		System.out.print("Hello World !");
	}
}
  1. 编译 javac java 文件,会生成一个class文件

  2. 运行class文件,java class文件

    image-20230103201021179

Java程序运行机制

  • 编译型(compile)

  • 解释型

  • 程序运行机制

查看源图像

Java基础语法

注释

  • 单行注释 //
  • 多行注释 /* 注释 */
  • JavaDoc: 文档注释 /** + 回车

标识符

  • 关键字
    • JAVA基础篇(常用关键字) - 知乎
  • Java所有组成部分都需要名字。类名、变量名以及方法名都被成为标识符
  • 标识符注意点
    • 所有标识符都应该以字母(A-Z或者a-z)、美元符($)、或者下划线(_)开始
    • 首字符之后可以是字母(A-Z或者a-z)、美元符($)、或者下划线(_)或数字的任何字符组成
    • 不能使用关键字作为变量名或方法名
    • 标识符大小写敏感的

数据类型

  • 强类型语言

    • 要求变量的使用要严格符合规定,所有变量都必修先定义后使用
  • 弱类型语言

  • img

  • 整数拓展

    数值 二进制0b 十进制 八进制0 十六进制0x
    2 0b10 2 02 0x2
  • 浮点数扩展

    •     float f = 0.1f;
          double d = 0.1;
      
          System.out.println(f==d);//false
      
          float d1 = 230585403405f;
          float d2 = d1 + 1;
      
          System.out.println(d1==d2);//true
      
    • float浮点型表示的数值是一个 有限 离散 舍入误差 大约 接近但不等于的数值,如上面的数值0.1,float和double赋值的大小相等,但是相比出来的结果判断为false,,除此之外,当将很大的数值赋值给float定义的变量,再相加1与原数值相比却判断为ture。

    • 最好完全避免使用浮点数进行比较

  • 字符扩展

  • 字符可以强制转换为数字(所有字符的本质还是数字)

  •   char c1 = 'a';
      char c2 = '中';
    
      System.out.println(c1);//a
      System.out.println((int)c1);//97
      System.out.println(c2);//中
      System.out.println((int)c2);//20013
    
  • ASCII表(97=a 65=A)

  • 编码 Unicode(统一码) 2字节 0-65536

  • 统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集编码方案等。

    统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

    实现方式

    在统一码中,汉字“字”对应的数字是23383。在统一码中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成统一码字符集转换格式,即怎样将统一码定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:

    BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97}; // UTF-8编码

    WORD data_utf16[] = {0x6c49, 0x5b57}; // UTF-16编码

    DWORD data_utf32[] = {0x6c49, 0x5b57}; // UTF-32编码

    这里用BYTE、WORD、DWORD分别表示无符号8位整数,无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD,大小是4个字节。“汉字”的UTF-32编码需要两个DWORD,大小是8个字节。根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。下面介绍UTF-8、UTF-16、UTF-32、字节序BOM

  • char c3 = '\u0061';
    System.out.println(c3);//a
    
  • 转义字符

- \t 制表符
- \n 换行

数据转换

  • 由于Java是强类型语言,所以要进行有些运算的时候,需要用到数据类型转换。

    低-------------------------------------------------------------->高

    byte,short,char--> int --> long --> float --> double

  • 运算中,不同类型的数据先转换为同一类型,然后进行运算

  • 强制类型转换 (类型)变量名 高-->低

  • 自动类型转换 低--->高

  • 注意点

    1. 不能对布尔值进行转换
    2. 不能把对象类型转化为不相干的类型
    3. 在把高容量转换为低容量的时候,强制转换
    4. 转换的时候可能存在内存溢出,或者精度问题(float类型的数值23.7,强制类型转换为int类型后数值输出为23,损失精度0.7)

变量

  • 变量是什么:就是可以变化的量!

  • Java是一种强类型语言,每个变量都必须声明其类型。

  • Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。

    type varName [=value] [{,varName[=value]}];

    //数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量

  • 注意事项:

    • 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
    • 变量名必须是合法的标识符。
    • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。

变量作用域

  • 类变量

  • 实例变量

  • 局部变量

    public class Variable{
        static int allClicks=0; //类变量
        String str="hello world";  //实例变量
    
        public void method(){
            int i=0; //局部变量
        }
    }
    

常量

  • 常量(Constant):初始化(initialize)后不再改变值!不会变动的值。

  • 所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许改变。

    //常量形式
    //final 常量名=值
    final double PI=3.14;
    
  • 常量名一般使用大写字符

变量的命名规范

  • 所有变量、方法、类名:见名知意
  • 类成员变量:首字母小写和驼峰原则:monthSalary
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun()

运算符

  • Java语言支持如下运算符:

    • 算数运算符:+,-,*,/,%,++,--(变量名--,先赋值,后自减;--变量名,先自减,再赋值)

    • 赋值运算符:=

    • 关系运算符:>,<, >=, ⇐, ==, != instanceof

    • 逻辑运算符:&&(与),||(或),!(非)

    • 位运算符:&,|,^(异或,相同为0,不同为1), ~(取反), >>(右移), <<(左移), >>> (了解!!!)

    • 条件运算符 ?:

    • 扩展运算符:+=, -=, *=, /=

      • //字符串连接符  + , String
                int a = 10;
                int b = 20;
        
                System.out.println(""+a+b);//1020, 字符串在前面,数值间进行拼接
                System.out.println(a+b+"");//30, 字符串在后面,数值间正常运算
        

包机制

  • 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间

  • 包语句的语法格式

    package pkg1[.pkg2[.pkg3...]];
    
  • 为了能够使用某一包的成员,我们需要在Java程序中明确导入该包,使用”import“语句可完成此功能

    import package1[.package2...].(classname|*)
    

JavaDoc生成文档

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

Java流程控制

用户交互Scanner

Scanner对象

  • 我们可以通过Scanner类来获取用户的输入。
  • 基本语法
Scanner s = new Scanner(System.in)
  • 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hastNext() 与 hasNextLine() 判断是否还有输入的数据。
    • next():
      1. 一定要读取到有效字符后才可以结束输入。
      2. 对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
      3. 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
      4. next()不能得到带有空格的字符串
    • nextLine():
      1. 以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
      2. 可以获得空格。

结构

顺序结构

  • JAVA的基本结构是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
  • 顺序结构是最简单的算法结构。image-20230105173817873
  • 语句与语句之间,框与框之间是按从上到下的顺序进行的。他是有若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。

选择结构

  • if单选择结构

    //语法
    if(布尔表达式){
        //如果布尔表示式的值为true
    }
    
  • if双选择结构

//语法
if(布尔表达式){
    //如果布尔表达式的值为true
}else{
    //如果布尔表达式的值为false
}
  • if多选择结构
//语法
if(布尔表达式1){
    //如果布尔表达式1值为true
}else if(布尔表达式2){
    //如果布尔表达式2值为true  
}else if(布尔表达式3){
     //如果布尔表达式3值为true 
}else{
    //如果布尔表达式1、2、3的值为false
}
  • 嵌套的if结构
  • switch多选择结构
    • switch语句中的变量类型可以是:
      • byte、short、int或者char
      • 从Java SE 7 开始,switch 支持字符串 String 类型了
      • 同时 case 标签必须为字符串常量或字面量。
//语法
Switch(expression){
    case value:
    //语句
    	break;//可选
    case value:
    //语句
    	break;//可选
    //可以有任意数量的case语句
    default://可选
            //语句
}

循环结构

  • while循环

    //结构
    while(布尔表达式){
        //循环内容
    }
    
  • do.....while循环

  • for循环

    • for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
    • for循环的特殊形式(“for( ; ?”等价于死循环)
    //结构
    for(初始化;布尔表达式;更新){
        //代码语句
    }
    
  • 在Java5中引入了一种主要用于数组的增强型for循环

    //增强for循环结构
    //for(声明语句 : 表达式){
        //代码
    //}
    
    //例子
    public class Demo05 {
        public static void main(String[] args) {
            int[] numbers = {10,20,30,40,50};
    
            for (int x:numbers){
                System.out.print(x+"\t");
            }
        }
    }
    //输出 
    10	20	30	40	50	
    

break、continue

  • break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)

  • continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

  • 关于goto关键字

    • goto关键字很早就在程序设计语言中出现。尽管goto语句仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto,然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue。

    • “标签”是指后面跟一个冒号的标识符,例如:label:

    • 对Java来说唯一用到标签的地方是在循环语句之前。而在循环语句之前没有设置标签的唯一理由是:我们希望在其中嵌套一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,他们就会中断到存在标签的地方。

      //例子
      public class LabelDemo {
          public static void main(String[] args) {
              //打印101-150之间的所有质数
              //质数是值在大于1的自然数中,除了1和它本身以外不再有其他因素的自然数
      
              int count = 0;
      
              outer:for (int i=101;i<150;i++){
                  for (int j = 2; j<i/2; j++){
                      if (i % j ==0){
                          continue outer;
                      }
                  }
                  System.out.print(i+"\t");
              }
          }
      }
      //结果:101	103	107	109	113	127	131	137	139	149	
      

Java方法

什么是方法

  • System.out.println(),是什么?

    //System.out.println()

    System---类

    out----实例对象

    println()---方法

  • Java方法是语句的集合,它们在一起执行一个功能。

    • 方法是解决一类问题的步骤有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其它地方被引用
  • 设计方法原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期的扩展

//例子
public class Demo01 {
    //main方法
    public static void main(String[] args) {
//        int sum = add(1,3);
//        System.out.println(sum);
        test();
    }

    //其它方法
    public static int add(int a, int b){
        return a+b;
    }

    public static void test(){
        for (int i = 1; i < 10; i++) {
            for (int i1 = 10; i1 >= i; i1--) {
                System.out.print(" ");
            }
            for (int i1 = 1; i1 <= i ; i1++) {
                System.out.print("*");
            }
            for (int i1 = 1; i1 < i; i1++) {
                System.out.printf("*");
            }
            System.out.println();
        }
    }
}

方法的定义及调用

  • Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

    • 方法包含一个方法头和一个方法体。下面是一个方法的所有部分。

      修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。

      返回值类型:方法可能会有返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字voide.

      方法名:是方法的实际名称。方法名和参数表共同构成方法签名。

      参数类型:参数像是一份占位符。但方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

      • 形式参数:在方法中被调用时用于接受外界输入的数据。

      • 实参:调用方法时实际传给方法的数据。

        public class Demo01 {
            //main方法
            public static void main(String[] args) {
                int sum = add(1,3);//1,3时实参
                System.out.println(sum);
        
            }
            //其它方法          a,b为形式参数
            public static int add(int a, int b){
                return a+b;
            }
        
        }
        

      方法体:方法体包含具体的语句,定义该方法的功能。

      修饰符 返回值类型  方法名(参数类型 参数名){
          ....
          方法体
          .....
          return 返回值;
      }
      
  • 方法调用

    1. 调用方法:对象名.方法名(实参列表)

    2. Java支持两种调用方法的方式,根据方法是否返回值来选择。

    3. 当方法返回一个值得时候,方法调用通常被当作一个值。例如:

      int larger = max(30,40);
      
    4. 如果方法返回值是void,方法调用一定是一条语句。

      //例如
      System.out.println("Hello World !")
      
  • 拓展:值传递与引用传递

    **值传递(pass by value)**是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

    **引用传递(pass by reference)**是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

方法的重载

  • 重载就是在一个类中,有相同的函数名称,但形参不同的函数。

  • 方法重载的规则:

    • 方法名称必相同。
    • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
    • 方法的返回类型可以相同也可以不相同。
    • 仅仅返回类型不同不足以成为方法的重载。
  • 实现理论:

    • 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

命令行传参

  • 通过命令行的形式去传参数

    //例子: 给main方法通过命令行的方式进行传参
    public class Demo02 {
        public static void main(String[] args) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("args["+ i + "]: "+ args[i]);
            }
        }
    }
    

    通过命令行传参“This is yuan”:

    image-20230109120241062

可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法

  • 在方法声明中,在指定参数类型后加一个省略号(...).

  • 一个方法中 只能指定一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

    public class Demo03 {
        public static void main(String[] args) {
            Demo03 demo03 = new Demo03();
            demo03.test(1,2,3);
        }
    
        public void test(int ... i){
            System.out.println(i[0]);
            System.out.println(i[1]);
            System.out.println(i[2]);
        }
    }
    //结果输出 1,2,3
    

递归

  • 递归就是方法自己调用自己。

  • 递归结构包括两个部分:

    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。

    • 递归体:什么时候需要调用自身的方法。

      //阶乘
      public class Demo04 {
          public static void main(String[] args) {
              System.out.println(f(3));
          }
          public static int f(int n){
             if (n==1){
                 return 1;//边界
             }else {
                 return n*f(n-1);
             }
          }
      }
      //输出结果 f(3)-----6
      

      image-20230109123210228

Java数组

数组描述

  • 数组的定义
    • 数组是相同类型数据的有序集合。
    • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
    • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

数组声明创建

  • 首先必须声明数组变量,才能在程序中使用数组。

    dataType[] arrayRefVar; //首选方法
    或
    dataType arrayRefVar; //效果相同,但不是首选方法
    
  • Java语言使用new操作符来创建数组,语法如下:

    dataType[] arrayRefVar = new dataType[arraySize];
    
  • 数组的元素是通过索引访问的,数组索引从0开始。

  • 获取数组长度:

    arrays.length
    

内存分析

  • Java内存分析

    img image-20230109170056028
  • 三种初始化

    • 静态初始化

      int[] a = {1,2,3};
      Man[] mans = {new Man(1,1),new Man(2,2)}
      
    • 动态初始化

      int[] a = new int[2];
      a[0] = 1;
      a[1] = 0;
      
    • 数组的默认初始化

      • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式隐式初始化。
  • 数组的四个基本特点

    1. 其长度是确定的。数组一旦创建,它的大小就是不可以改变的。

    2. 其元素必须式相同类型,不允许出现混合类型。

    3. 数组中的元素可以是任何数据类型,包括基本类型和引用类型。

    4. 数组变量属于引用类型,数组也可以看成式对象,数组中的每个元素相当于该对象的成员变量。

      数组本身就是对象,Java中对象是在堆中,因此数组无论保存原始类型还是其他对象,数组对象本身是在堆中的。

  • 数组边界

    • 下标的合法区间:[0:length-1],如果越界就会报错;
    public static void main(String[] args){
        int[] a = new int[2];
        System.out.println(a[2]);
    }
    //结果:
    ArrayIndexOutOfBoundsException:数组下标越界异常!
    

数组使用

  • For-Each

    public class ArrayDemo03 {
        public static void main(String[] args) {
            int[] arrays = {1,2,3,4,5,6};
            for (int array : arrays) {
                System.out.print(array+"\t");
            }
        }
    }
    //结果 1 2 3 4 5 6
    
  • 数组作方法入参

    public static void main(String[] args) {
            int[]  nums = {2,3,5,6,7,9};
            printNums(nums);
        }
        public static void printNums(int[] numbers){
            for (int i = 0; i < numbers.length; i++) {
                System.out.print(numbers[i]+"\t");
            }
        }
    //结果 2 3 5 6 7 9
    
  • 数组作为返回值

多维数组

  • 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

  • 二维数组

    //两行五列的数组
    int a[][] = new int[2][5];
    

Arrays类

  • 数组的工具类是java.util.Arrays
  • 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(是”不用“而不是”不能“)
  • 具有以下常用功能:
    • 给数组赋值:通过fill方法。
    • 对数组排序:通过sort方法,按升序。
    • 比较数组:通过equals方法比较数组中元素是否相等。
    • 查找数组元素:通过binarySearch方法能对排好序的数组进行二分查找法操作。

冒泡排序:

//冒泡排序
    //1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置。
    //2.每一次比较,都会产生出一个最大,或者最小的数字;
    //3.下一轮则可以少一次排序
    //4.依次循环,知道结束
public class ArrayDemo05 {
    public static void main(String[] args) {
        int[] a = {1,3,5,465,6,6,5274,23};
        int[] result = sort(a);
		System.out.println(Arrays.toString(result));
    }
    public static int[] sort(int[] array){
        int temp = 0;
        for (int i = 0; i < array.length-1; i++) {
            for (int i1 = 0; i1 < array.length - 1 - i; i1++) {
                if (array[i1+1]>array[i1]){
                    temp = array[i1+1];
                    array[i1+1] = array[i1];
                    array[i1] = temp;
                }
            }
        }
        return array;
    }
}
//结果 [5274, 465, 23, 6, 6, 5, 3, 1]

稀疏编码

  • 稀疏数组介绍

    • 当一个数组中的大部分元素为0.或者为同一值的数组时,可以使用稀疏数组来保存该数组。

    • 稀疏数组的处理方式:

      • 记录数组一共有几行几列,有多少个不同值
      • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

      img

    • 上图中左边为原始数组,右边为稀疏数组

      [0] 6 7 8 #这一列代表的的是,6-原始数组有六行,7-原始数组有七列,8-原始数组共有8个不为0的值
      #############
      [1] 0 3 22 #记录第一个值:即第1行第3列的值为22
      ....
      ...
      [8] 5 2 28 #记录第八个值:即第6行第3列的值为28
      
      
      
      //例子
      public class ArrayDemo06 {
          public static void main(String[] args) {
              //1.创建一个而二维数组 11*11   0:没有棋子, 1:黑棋  2:白棋
              int[][] array = new int[11][11];
              array[1][2] = 1;
              array[2][3] = 2;
              //输出原始的数组
              System.out.println("输出原始数组:");
      
              for (int[] ints : array) {
                  for (int anInt : ints) {
                      System.out.print(anInt + "\t");
                  }
                  System.out.println();
              }
      
              //转换为稀疏数组
              //获取有效值的个数
              int sum = 0;
              for (int i = 0; i < array.length; i++) {
                  for (int i1 = 0; i1 < array[i].length; i1++) {
                      if (array[i][i1] != 0){
                          sum++;
                      }
                  }
              }
              System.out.println("有效值个数为:"+sum);
      
      
              //创建稀疏数组
              int[][] array2 = new int[sum+1][3];
      
              array2[0][0] = 11; //原始数组行数
              array2[0][1] = 11; //原始数组列数
              array2[0][2] = sum; //原始数组有效数
      
              //遍历二维数组,将非零的值。存放稀疏数组中
              int count = 0;
              for (int i = 0; i < array.length; i++) {
                  for (int j = 0; j < array[i].length; j++){
                      if (array[i][j]!=0){
                          count++;
                          array2[count][0] = i;
                          array2[count][1] = j;
                          array2[count][2] = array[i][j];
                      }
                  }
              }
              //输出稀疏数组
              System.out.println("count值为:"+count);
              System.out.println("稀疏数组:");
              for (int[] ints : array2) {
                  for (int anInt : ints) {
                      System.out.print(anInt + "\t");
                  }
                  System.out.println();
              }
      
              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();
              }
          }
      }
      //结果:
      输出原始数组:
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	1	0	0	0	0	0	0	0	0	
      0	0	0	2	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      有效值个数为:2
      count值为:2
      稀疏数组:
      11	11	2	
      1	2	1	
      2	3	2	
      ===================
      还原稀疏数组
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	1	0	0	0	0	0	0	0	0	
      0	0	0	2	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      0	0	0	0	0	0	0	0	0	0	0	
      

学习地址: