JavaSE(简介)

1. Java语言特性

  1. 简单

Java语法是C++语法的一个"纯净版本",相当于对C++做了一个减法。这里没有头文件、指针运算(甚至指针 语法)、结构、联合、操作符重载、虚基类等等。不仅如此,Java开发环境远远超出大多数其他编程语言的开 发环境。

  1. 面相对象

在Java的世界里,一切皆对象。比如:人、狗、手机、电脑等都是对象。所谓面相对象,就是依靠对象之间 的交互来完成事情。

  1. 分布式(微服务)

Java有丰富的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网络

上的对象,其便捷程度就好像访问本地文件一样。

  1. 健壮性

Java采用的指针模型可以消除重写内存和损坏数据的可能性,Java编译器能够 检测许多在其他语言中仅在运行时才能够检测出来的问题。

  1. 安全性

Java适用于网络/分布式环境。为了达到这个目标,在安全性方面投入了大量的精力。使用Java可以构建防病

毒、防篡改的系统

  1. 体系结构中立

编译器生成一个体系结构中立的目标文件格式,按照该中规范生成的文件,只要有Java运行时系统,这些编译后的代码就可以在许多处理器上运行。Java编译器通过生成与特定计算机体系结构无关的字节码指令来实现 这一特性。字节码不仅可以很容易的在任何机器上解释执行,而且还可以动态地翻译成本地机器代码。"Wrice once,Run anywhere"。其他语言编写的程序,在编译后如果能够严格按照字节码文件的规范生成.class文件,也可以在JVM上运行。

7.可移植性

在Java中,数据类型具有固定的大小,这消除了代码移植时的主要问题。

  1. 解释性

Java为了实现与平台无关,自己维护了一套基于栈架构的指令集,Java源代码经过编译之后,字节码文件中的指令就是按照自己的指令集来组织的,但是在具体硬件环境中运行时,系统并不能识别,因为Java程序在执行 时,Java解释器会逐条的将字节码文件中的指令翻译成CPU的指令集。

  1. 高性能

边解释边执行,垃圾回收等导致了Java代码运行效率偏低,近年来JVM也在不断的优化,比如:JIT(即时编译器),热点代码探测,让Java程序的执行效率大幅提高。

  1. 多线程

Java是第一个支持并发程序设计的主流语言,多线程可以带来更好的交互响应和实时行为。

  1. 动态性

它能够适应不断发展的环境,库中可以自由的添加新方法和实例变量,而对客户端没有任何影响。在Java中找出运行时类型信息十分简单。Java不仅仅是一门编程语言,也是一个由一些列计算机软件和规范组成的技术体系。

2. Java程序的运行

Java是一门半编译型、半解释型语言。先通过javac编译程序把源文件进行编译,编译后生成的.class文件是由字节 码组成的平台无关、面向JVM的文件。最后启动java虚拟机来运行.class文件,此时JVM会将字节码转换成平台能够 理解的形式来运行。

在运行Java程序前,必须先安装好JDK(Java Development Kit即Java开发工具包),JDK里面就包含了javac和 java工具,Java程序最终是在JVM(Java虚拟机)中运行的。
JDK、JRE、JVM之间的关系:

  • JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译器javac与自带的调试工具Jconsole、jstack等。
  • JRE(Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程 序运行的所需环境。
  • JVM:Java虚拟机,运行Java代码

3. 关键字

  • 用于定义访问权限修饰符:private, protected, public,default
  • 用于定义类,函数,变量修饰符:abstract, final, static, synchronized
  • 用于定义类与类之间的关系:extends,implements
  • 用于定义建立实例及引用实例,判断实例:new,this,super,instanceof
  • 用于异常处理:try,catch,finally,throw,throws
  • 用于包:package,import
  • 其他修饰符关键字:native,strictfp,transient,volatile,assert

4. 注释

  • 单行注释:// 注释内容(用的最多)
  • 多行注释:/* 注释内容*/(不推荐)
  • 文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可以被javadoc工具解析,生 成一套以网页文件形式体现的程序说明文档
  1. 多行注释不能嵌套使用
  2. 不论是单行还是多行注释,都不参与编译,即编译之后生成的.class文件中不包含注释信息。

5. 标识符

在程序中由用户给类名、方法名或 者变量所取的名字。

由数字,字母,下划线,美元符号组成,

不能以数字、关键字开头,且严格区分大小写。

建议 :

  • 类名 :每个首字母大写(大驼峰)
  • 方法名:首字母小写,后面每个字母的首字母大写(小驼峰)
  • 变量名:首字母小写,后面每个字母的首字母大写(小驼峰)

6. 字面常量

常量即程序运行期间,固定不变的量称为常量

示例:

java 复制代码
System.Out.println("Hello World");

不论程序何时运行,输出的都是Hello World,其实"Hello World"就是字面常量。

6.1 字面常量的分类

  1. 字符串常量:由""括起来的,比如"12345"、"hello"、"你好"。
  2. 整形常量:程序中直接写的数字(注意没有小数点),比如:100、1000 。
  3. 浮点数常量:程序中直接写的小数,比如:3.14、0.49。
  4. 字符常量:由 单引号 括起来的当个字符,比如:'A'、'1'。
  5. 布尔常量:只有两种true和false。
  6. 空常量:null。

7. 数据类型

7.1 四类基本数据类型

整型,浮点型,字符型,布尔型

7.1.1 八种

byte,short,int,long,float,double,char,boolean。

  • 不论是在16位系统还是32位系统,int都占用4个字节,long都占8个字节
  • 整形和浮点型都是带有符号的
  • 整型默认为int型,浮点型默认为double
    字节是计算机中表示空间大小的基本单位.

计算机使用二进制表示数据. 我们认为 8 个二进制位(bit) 为一个字节(Byte). 我们平时的计算机为 8GB 内存, 意思是 8G 个字节.其中 1KB = 1024 Byte, 1MB = 1024 KB, 1GB = 1024 MB.所以 8GB 相当于 80 多亿个字节.

7.2 引用数据类型String

7.2.1 String类的构造方式:

使用常量串构造:

直接newString对象:

使用字符数组进行构造:

String是引用类型,内部并不存储字符串本身,在JDK1.8中,字符串实际保存在char类型的数组中。在Java中""引起来的也是String类型对象。

7.2.1.1 字符串常量池:

为了节省存储空间以及程序的运行效率,Java中引入了:

  • Class文件常量池:
    每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息。
  • 运行时常量池:
    在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份。
  • 字符串常量池:
    字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable在堆中 ,大小可设置,有范围限制,最小是1009。
7.2.1.2 String对象创建的区别:
  • 直接使用字符串常量进行赋值:
    在字节码文件加载时,常量串已经加载好了并保存在字符串常量池中,创建对象时,先在字符串常量池中找,将字符串引用赋值给对象。使用常量串创建String类型对象的效率更高,而且更节省空间,也可以将创建的字符串对象通过 intern 方式添加进字符串常量池中。
  • 通过new创建String类对象:
    只要是new的对象,都是唯一的。
  1. String str = "hello":
    只会开辟一块堆内存空间,保存在字符串常量池中,然后str共享常量池中的String对象。
  2. String str = new String("hello"):
    会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象给新开辟的String对象赋值。
  3. String str = new String(new char[]{'h', 'e', 'l', 'l', 'o'}):
    先在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中。
7.2.1.3 字符串的不可变性:

String是一种不可变对象. 字符串中的内容是不可改变。

String类中的字符实际保存在内部维护的value字符数组中,而且String类被final修饰表明该类不能被继承,value被修饰被final修饰表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。

final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象。

7.2.1.3.1 为什么 String 要设计成不可变的?
  1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
  2. 不可变对象是线程安全的.
  3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中

7.2.2 String对象的比较:

  • ==

    比较是否引用同一个对象(对于内置类型,== 比较的是变量中的值;对于引用类型 == 比较的是引用中的地址)。

  • boolean equals(Object anObject) 方法

    按照字典序(字符大小的顺序)比较。先检测this 和 anObject 是否为同一个对象比较,如果是返回true,检测anObject是否为String类型的对象,如果是继续比较,否则返回false,将anObject向下转型为String类型对象,this和anObject两个字符串的长度是否相同,是继续比较,否则返回false,按照字典序,从前往后逐个字符进行比较。

  • int compareTo(String s) 方法

    按照字典序进行比较:1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值,2. 如果前k个字符相等(k为两个字符长度最小值),返回两个字符串长度差值。

  • int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较。

7.2.3 字符串查找:

  • char charAt(int index):返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常。
  • int indexOf(int ch) :返回ch第一次出现的位置,没有返回-1。
    int indexOf(int ch, int fromIndex):从fromIndex位置开始找ch第一次出现的位置,没有返回-1。
  • int indexOf(String str):返回str第一次出现的位置,没有返回-1。
  • int indexOf(String str, intfromIndex):从fromIndex位置开始找str第一次出现的位置,没有返回-1。
  • int lastIndexOf(int ch):从后往前找,返回ch第一次出现的位置,没有返回-1。
  • int lastIndexOf(int ch, int fromIndex):从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1。
    int lastIndexOf(String str) :从后往前找,返回str第一次出现的位置,没有返回-1。
  • int lastIndexOf(String str, int fromIndex):从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1。

7.2.4 转化:

  • 数值和字符串转化:Integer.parseInt()Double.parseDouble()......
  • 大小写转换:toUpperCase(),toLowerCase()。
  • 字符串转数组:toCharArray(),
  • 数组转字符串:new String(ch)
  • 格式化:format("%d-%d-%d", 2019, 9,14)

7.2.5 替换:

  • 替换所有的指定内容:String replaceAll(String regex, String replacement)
  • 替换首个内容:String replaceFirst(String regex, String replacement)

由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串。

7.2.6 字符串拆分:

  • 将字符串全部拆分:String[] split(String regex)
  • 将字符串以指定的格式,拆分为limit组:String[] split(String regex, int limit)

字符"|","*","+"都得加上转义字符,前面加上 "\" .

而如果是 "" ,那么就得写成 "\\" .

如果一个字符串中有多个分隔符,可以用"|"作为连字符.

7.2.7 字符串截取:

  • 从指定索引截取到结尾:String substring(int beginIndex)
  • 截取部分内容:String substring(int beginIndex, int endIndex) 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

7.2.8 字符串修改:

尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下,如果要修改建议尽量使用StringBuffer或者StringBuilder。

7.2.8.1 String和StringBuilder类转换。
  • String变为StringBuilder: 利用StringBuilder的构造方法或append()方法。
  • StringBuilder变为String: 调用toString()方法。
7.2.8.2 String、StringBuffer、StringBuilder的区别:
  • String的内容不可修改,StringBuffer与StringBuilder的内容可以修改。
  • StringBuffer与StringBuilder大部分功能是相似的。
  • StringBuffer采用同步处理,属于线程安全操作;而- StringBuilder未采用同步处理,属于线程不安全操作。

7.2.9 其他方法

  • 去掉字符串中的左右空格,保留中间空格:String trim() ,trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等)
  • 字符串转大写:String toUpperCase()
  • 字符串转小写:String toLowerCase()

8. 枚举类型

在Java当中枚举实际上就是一个类,将常量组织起来统一进行管理,是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。枚举的构造方法默认是私有的。枚举常量更简单安全 。 枚举具有内置方法 ,代码更优雅,但是不可继承,无法扩展。应用场景:错误状态码,消息类型,颜色的划分,状态机等等...

Enum 类的常用方法:

以数组形式返回枚举类型的所有成员values() ;获取枚举成员的索引位置ordinal() ;将普通字符串转换为枚举实例valueOf() ;比较两个枚举成员在定义时的顺序compareTo()。

9. 变量

有些内容可能会经常改变,在Java程序中,称为变量,数据类型就是用来定义不同种类变量的。

9.1 语法格式

java 复制代码
数据类型  变量名 = 初始值;

示例:

java 复制代码
int a = 10;   // 定义整形变量a,a是变量名也称为标识符,该变量中放置的值为10

double d = 3.14; 
char c = 'A'; 
boolean b = true;

9.2 整型(int)变量

  1. int不论在何种系统下都是4个字节
  2. 如果没有合适的初始值,可以设置为0
  3. 在给变量设置初始值时,值不能超过int的表示范围,否则会导致溢出
  4. 变量在使用之前必须要赋初值,否则编译报错
  5. int的包装类型为 Integer

9.3 长整型(long)变量

  1. 长整型变量的初始值后加L或者l,推荐加L
  2. 长整型不论在那个系统下都占8个字节
  3. 长整型的表示范围为: ~
  4. long的包装类型为Long

9.4 短整型(short)变量

  1. short在任何系统下都占2个字节
  2. short的表示范围为:-32768 ~ 32767
  3. 使用时注意不要超过范围(一般使用比较少)
  4. short的包装类型为Short

9.5 字节型(byte)变量

  1. byte在任何系统下都占1个字节
  2. byte的范围是:-128 ~ 127
  3. 字节的包装类型为Byte

9.6 双精度浮点型(double)变量

  1. double在任何系统下都占8个字节
  2. 浮点数与整数在内存中的存储方式不同,不能单纯使用 的形式来计算
  3. double的包装类型为Double
  4. double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势
    必会存在一定的精度误差,因此浮点数是个近似值,并不是精确值。
  5. 在 Java 中, int 除以 int 的值仍然是 int(会直接舍弃小数部分)。如果想得到 0.5, 需要使用 double 类型计算.

9.7 单精度浮点型(float)变量

float 类型在 Java 中占四个字节, 同样遵守 IEEE 754 标准. 由于表示的数据精度范围较小, 一般在工程上用到浮点数 都优先考虑 double, 不太推荐使用 float. float的包装类型为Float。

9.8 字符型(char)变量

  1. Java 中使用 单引号 + 单个字母 的形式表示字符字面值.
  2. 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符. 因此 一个字符占用两个字节, 表示的字符种类更多, 包括中文.
  3. char的包装类型为Character

9.9 布尔型(boolean)变量

  1. boolean 类型的变量只有两种取值, true 表示真, false 表示假.
  2. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法.

9.10 类型转换

Java 是一个强类型编程语言, 当不同类型之间的变量相互赋值的时候, 会有教严格的校验.

  1. 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型
  2. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失
  3. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查
  4. 强制类型转换不一定能成功,不相干的类型不能互相转换

9.10.1 自动类型转换(隐式)

代码不需要经过任何处理,在代码编译时,编译器会自动进行处理。数据范围小的转为数 据范围大的时会自动进行。

9.10.1 强制类型转换(显式)

当进行操作时,代码需要经过一定的格式处理,不能自动完成。

特点:数据范围大的到数据范围小的。

9.11 类型提升

不同类型的数据之间相互运算时,数据类型小的会被提升到数据类型大的。

  1. int与long之间:int会被提升为long

  2. byte与byte的运算:

    java 复制代码
    byte a = 10; 
    byte b = 20; 
    byte c = a + b;
    System.out.println(c);
    
    // 编译报错
    Test.java:5: 错误: 不兼容的类型: 从int转换到byte可能会有损失 

    byte 和 byte 都是相同类型, 但是出现编译报错. 原因是, 虽然 a 和 b 都是 byte, 但是计算 a + b 会先将 a 和 b 都提升成 int, 再进行计算, 得到的结果也是 int, 这是赋给 c, 就会出现上述错误.由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据. 为了硬件上实现方便, 诸如 byte 和 short 这种低于 4 个字节的类型, 会先提升成 int, 再参与计算。
    正确的写法:

    java 复制代码
    byte a = 10; 
    byte b = 20; 
    byte c = (byte)(a + b);
    System.out.println(c);

10. 数组

  • 数组数组是引用类型,可以看成是相同类型元素的一个集合,在内存中是一段连续的空间。
    1. 数组中存放的元素其类型相同
    2. 数组的空间是连在一起的
    3. 每个空间有自己的编号,其实位置的编号为0,即数组的下标。

10.1 数组的创建格式

java 复制代码
T[] 数组名 = new T[N];

10.2 数组的初始化

如果没有对数组进行初始化,数组中元素有其默认值,如果数组中存储元素类型为引用类型,默认值为null, 如果数组中存储元素类型为基类类型,默认值为基类类型对应的默认值

  1. 动态初始化:在创建数组时,直接指定数组中元素的个数
java 复制代码
int[] array = new int[10];
  1. 静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定

    java 复制代码
    T[] 数组名称 = {data1, data2, data3, ..., datan}
    
    int[] array1 = new int[]{0,1,2,3,4,5,6,7,8,9};
    double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0}; 
    String[] array3 = new String[]{"hell", "Java", "!!!"};

静态初始化时, {}中数据类型必须与[]前数据类型一致。

静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中元素个数来确定数组的长度。

静态初始化可以简写,省去后面的new T[]。

静态和动态初始化也可以分为两步,但是省略格式不可以。

java 复制代码
int[] array1;
array1 = new int[10];

int[] array2;
array2 = new int[]{10, 20, 30};

// 注意省略格式不可以拆分, 否则编译失败 // int[] array3;
// array3 = {1, 2, 3};

10.3 数组的使用

10.3.1 数组中元素访问

数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,支持随机访问,数组可以通过下标访问其任意位置的元素。下标从0开始,介于[0, N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常。

java 复制代码
int[]array = new int[]{10, 20, 30, 40, 50}; 
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]); 
System.out.println(array[3]);
System.out.println(array[4]);

10.3.2 遍历数组

"遍历" 是指将数组中的所有元素都访问一遍, 访问是指对数组中的元素进行某种操作。

java 复制代码
int[]array = new int[]{10, 20, 30, 40, 50}; 
for(int i = 0; i < array.length; i++){ 
    System.out.println(array[i]);
}    
java 复制代码
int[] array = {1, 2, 3};
for (int x : array) { 
    System.out.println(x);
}

10.4 数组的存储

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值; 而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。

引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。

示例:

java 复制代码
 public static void func() { 
    int a = 10;
    int b = 20;
    int[] arr = new int[]{1,2,3};
 }   
 

在上述代码中,a、b、arr,都是函数内部的变量,因此其空间都在main方法对应的栈帧中分配。 a、b是内置类型的变量,因此其空间中保存的就是给该变量初始化的值。 array是数组类型的引用变量,其内部保存的内容可以简单理解成是数组在堆空间中的首地址。

10.4.1 数组的修改

java 复制代码
public static void func() { 
    int[] array1 = new int[3];
    array1[0] = 10; 
    array1[1] = 20; 
    array1[2] = 30;
    int[] array2 = new int[]{1,2,3,4,5}; 
    array2[0] = 100;
    array2[1] = 200;
    array1 = array2; 
    array1[2] = 300; 
    array1[3] = 400; 
    array2[4] = 500; 
    for (int i = 0; i < array2.length; i++) {
       System.out.println(array2[i]); 
    }


10.4.2 数组拷贝

  1. 借助copyOf() 方法
java 复制代码
import java.util.Arrays;

public static void func(){
    // newArr和arr引用的是同一个数组
    // 因此newArr修改空间中内容之后,arr也可以看到修改的结果 
    int[] arr = {1,2,3,4,5,6};
    int[] newArr = arr;
    newArr[0] = 10;
    System.out.println("newArr: " + Arrays.toString(arr));

    // 使用Arrays中copyOf方法完成数组的拷贝:
    // copyOf方法在进行数组拷贝时,创建了一个新的数组
    // arr和newArr引用的不是同一个数组
    arr[0] = 1;
    newArr = Arrays.copyOf(arr, arr.length); 
    System.out.println("newArr: " + Arrays.toString(newArr));

    // 因为arr修改其引用数组中内容时,对newArr没有任何影响 
    arr[0] = 10;
    System.out.println("arr: " + Arrays.toString(arr)); 
    System.out.println("newArr: " + Arrays.toString(newArr));

    // 拷贝某个范围.
    int[] newArr2 = Arrays.copyOfRange(arr, 2, 4); 
    System.out.println("newArr2: " + Arrays.toString(newArr2));
}

  1. 实现copyOf()
java 复制代码
public static int[] copyOf(int[] arr) { 
    int[] ret = new int[arr.length]; 
    for (int i = 0; i < arr.length; i++) { 
        ret[i] = arr[i];
    }
    return ret;
}

10.4 二维数组

  1. 基本语法
java 复制代码
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };

使用示例:

java 复制代码
int[][] arr = { 
    {1, 2, 3, 4}, 
    {5, 6, 7, 8}, 
    {9, 10, 11, 12}
};

for (int row = 0; row < arr.length; row++) { 
    for (int col = 0; col < arr[row].length; col++) { 
        System.out.printf("%d\t", arr[row][col]);
    }
    System.out.println("");



// 执行结果
1       2       3       4
5       6       7       8
9       10      11      12

10.5 数组练习

10.5.1 求数组中元素的平均值

java 复制代码
public static void main(String[] args) { 
    int[] arr = {1,2,3,4,5,6}; 
    System.out.println(avg(arr));
}
public static double avg(int[] arr) {
    int sum = 0;
    for (int x : arr) {
        sum += x;
    }
    return (double)sum / (double)arr.length;
}


// 执行结果 
3.5

10.5.2 查找数组中指定元素(顺序查找)

java 复制代码
public static void main(String[] args) { 
    int[] arr = {1,2,3,10,5,6}; 
    System.out.println(find(arr, 10));
}

public static int find(int[] arr, int data) { 
    for (int i = 0; i < arr.length; i++) { 
        if (arr[i] == data) {
            return i;
        }
    }
    return -1;  // 表示没有找到   
}

// 执行结果
3

10.5.3 查找数组中指定元素(二分查找)

针对有序数组, 可以使用更高效的二分查找.

以升序数组为例, 二分查找的思路是先取中间位置的元素, 然后使用待查找元素与数组中间元素进行比较: 如果相等,即找到了返回该元素在数组中的下标

如果小于,以类似方式到数组左半侧查找 如果大于,以类似方式到数组右半侧查找

java 复制代码
public static void main(String[] args) { 
    int[] arr = {1,2,3,4,5,6}; 
    System.out.println(binarySearch(arr, 6));
}

public static int binarySearch(int[] arr, int toFind) { 
    int left = 0;
    int right = arr.length - 1;
    while (left <= right) {   
             int mid = (left + right) / 2; 
        if (toFind < arr[mid]) { 
            // 去左侧区间找 
            right = mid - 1;
        } else if (toFind > arr[mid]) { 
            // 去右侧区间找
            left = mid + 1;
        } else {
            // 相等, 说明找到了 
            return mid;
        }
    }
    // 循环结束, 说明没找到 
    return -1;
}

// 执行结果
5

10.5.4 冒泡排序

假设排升序:

  1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素 就在数组的末尾
  2. 依次从上上述过程,直到数组中所有的元素都排列好
java 复制代码
public static void main(String[] args) { 
    int[] arr = {9, 5, 2, 7};
    bubbleSort(arr); 
    System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int[] arr) { 
    for (int i = 0; i < arr.length; i++) { 
        for (int j = 1; j < arr.length-i; j++) { 
            if (arr[j-1] > arr[j]) {
                int tmp = arr[j - 1]; 
                arr[j - 1] = arr[j];
                arr[j] = tmp;
            }
        }
    } // end for
}  // end bubbleSort    


// 执行结果
[2, 5, 7, 9]

Java 中内置了更高效的排序算法:

java 复制代码
public static void main(String[] args) { 
   int[] arr = {9, 5, 2, 7};
   Arrays.sort(arr); 
   System.out.println(Arrays.toString(arr));
}    

10.5.5 数组逆序

设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.

然后让前一个下标自增, 后一个下标自减, 循环继续即可.

java 复制代码
public static void main(String[] args) { 
    int[] arr = {1, 2, 3, 4};
    reverse(arr); 
    System.out.println(Arrays.toString(arr));
}

public static void reverse(int[] arr) { 
    int left = 0;
    int right = arr.length - 1;
    while (left < right) {
        int tmp = arr[left];
        arr[left] = arr[right]; 
        arr[right] = tmp;
        left++;
        right--; 
    }
}

11. 运算符

  • 算术运算符:±*/

  • 增量运算符:+= -= *= %=

  • 自增自减运算符:++ --

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

  • 逻辑运算符:&&,||,!

  • 位运算符:

    • &(如果两个二进制位都是 1, 则结果为 1, 否则结果为 0)
    • |(如果两个二进制位都是 0, 则结果为 0, 否则结果为 1)
    • ^ (如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1)
    • ~(如果该位为 0 则转为 1, 如果该位为 1 则转为 0)
  • 移位运算符:

    java 复制代码
    <<(最左侧位不要了, 最右侧补 0)
    >>(最右侧位不要了, 最左侧补符号位(正数补0, 负数补1))
    >>>(最右侧位不要了, 最左侧补 0)
  • 条件运算符:表达式1 ? 表达式2 : 表达式3

13. 逻辑控制

顺序结构:按照代码书写的顺序一行一行执行。

分支结构:if,switch(只能是以下类型:byte、char、short、int,String常量串、枚举类型)

循环结构:

while(break(让循环提前结束),continue(跳过这次循环, 立即进入下次循环)),for,do while

相关推荐
魔道不误砍柴功1 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2341 分钟前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨4 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天3 小时前
java的threadlocal为何内存泄漏
java
caridle3 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^3 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋33 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花3 小时前
【JAVA基础】Java集合基础
java·开发语言·windows