JDK:Java程序的开发工具包
JRE:Java程序运行环境
JVM:Java虚拟机
JDK = JRE + 开发工具
JRE = JVM + 核心类库libs
一、和数学运算相关的类
1、java.lang.Math类
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
(1)double Math.PI
(2)double Math.sqrt(double x)
(3)double Math.random():返回[0,1)的随机值
(4)double/int/… abs(x):求x的绝对值
(5)double ceil(double a) :向上取整
(6)double floor(double a) :向下取整
(7)long round(double a) :四舍五入
(8)double pow(double a, double b) :求a的b次方
(9)double max(double a, double b):求a和b的最大值
(10)double min(double a, double b):求a和b的最小值
…
2、java.math包
BigInteger和BigDecimal,它们都是引用数据类型,用对象来表示数值。
(1)BigInteger:表示大整数
当long类型的变量都无法表示的数据,就可以用BigInteger
面试题:int,Integer,BigInteger什么区别?
int:基本数据类型
Integer:是int的包装类,支持与int自动装箱与拆箱
BigInteger:是引用数据,用于表示特别大的整数
(2)BigDecimal:表示任意精度的小数
之前float和double是浮点型小数。
面试题:double,Double,BigDecimal
double:基本数据类型,浮点型,不精确的
Double:是double的包装类,可以与double类型自动装箱与拆箱
BigDecimal:是引用数据类型,是可以表示任意精度的小数
3、java.util.Random类
用于产生随机值
boolean nextBoolean();
double nextDouble();
int nextInt();
long nextLong();
int nextInt(int bound):产生[0,bound)范围的int值
public class Math {
@Test
public void test05(){
Random random = new Random();
System.out.println(random.nextBoolean());
System.out.println(random.nextDouble());
System.out.println(random.nextInt());
//产生[0,10)范围的整数
System.out.println((int)(Math.random()*10));
System.out.println(random.nextInt(10));
}
@Test
public void test04(){
double largeNum = 1.23456789012345678901234567890;
System.out.println(largeNum);//1.2345678901234567 近似处理
BigDecimal big = new BigDecimal("1.23456789012345678901234567890");
System.out.println(big);
BigDecimal big1 = new BigDecimal("112.3456789012345678901234567890");
BigDecimal big2 = new BigDecimal("9.23456789012345678901234567890");
// System.out.println("和:" + (big1 + big2));//不支持直接使用+运算符
//对象想要完成xx功能,就是调方法
System.out.println("和:" + big1.add(big2));
System.out.println("减:" + big1.subtract(big2));
System.out.println("乘:" + big1.multiply(big2));
// System.out.println("除:" + big1.divide(big2));//除不尽
//这里报ArithmeticException
System.out.println("除:" + big1.divide(big2,30,BigDecimal.ROUND_UP));
System.out.println("余:" + big1.remainder(big2));
}
@Test
public void test03(){
// long largeNum = 123456789012345678901234567890L;
BigInteger big1 = new BigInteger("1123456789012345678901234567890");
BigInteger big2 = new BigInteger("923456789012345678901234567890");
// System.out.println("和:" + (big1 + big2));//不支持直接使用+运算符
//对象想要完成xx功能,就是调方法
System.out.println("和:" + big1.add(big2));
System.out.println("减:" + big1.subtract(big2));
System.out.println("乘:" + big1.multiply(big2));
System.out.println("除:" + big1.divide(big2));//整数/整数结果值保留整数部分
System.out.println("余:" + big1.remainder(big2));
}
@Test
public void test01(){
System.out.println(Math.ceil(2.3));//3.0
System.out.println(Math.floor(2.3));//2.0
System.out.println(Math.round(2.3));//2
}
@Test
public void test02(){
System.out.println(Math.ceil(2.7));//3.0
System.out.println(Math.floor(2.7));//2.0
System.out.println(Math.round(2.7));//3
}
}
二 、日期时间相关的API
(一)JDK1.8之前:
1、java.util.Date类:类 Date 表示特定的瞬间,精确到毫秒。
要区别于java.sql.Date。
java.sql.Date是java.util.Date的子类,用于和数据库中的日期时间映射用的。
(1)Date():获取系统时间
(2)Date(毫秒):根据毫秒值,得到对应的日期时间
(3)long getTime():距离1970年1月1日凌晨的经历的毫秒值
为什么选择1970年1月1日时间作为基准?
因为操作系统的时间基准是以Unix操作系统一开始选择的时间基准为标准的。
Unix操作系统一开始选择1970年1月1日这个为基准点。
当时的操作系统都是32位的,long类型的表示不了太长的值。
2、java.util.Calendar:日历类型
作为Date类型的一个补充。
它有一个直接子类:GregorianCalendar
(1)获取对象:
Calendar getInstance():使用当前系统默认的时区,语言环境来返回的日历对象
Calendar getInstance(TimeZone,Locale):根据指定的时区与语言环境来获取日历对象
(2)get(常量字段):根据常量字段,获取对应的时间值
3、java.util.TimeZone:时区
static TimeZone getTimeZone(String ID)
4、java.util.Locale:语言环境
Locale.常量对象
回忆:获取对象
(1)直接new
(2)类名.常量对象:适用于枚举
(3)调用方法得到xx对象
5、java.text.DateFormat与SimpleDateFormat
y:年
M:月
d:日
H:24小时制的小时
h:12小时制的小时
m:分
s:秒
S:毫秒
E:星期
D:一年的第几天
public class Date {
@Test
public void test08(){
//Date
Date now = new Date();
System.out.println(now);//Tue Jan 07 09:28:30 CST 2020 不符合我们中国人的日期时间表示习惯
//可以逐项获取,太麻烦
Calendar c = Calendar.getInstance();
System.out.println(c);
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
//使用DateFormat,日期格式化
//DateFormat抽象类,
DateFormat df = DateFormat.getDateInstance();
String s = df.format(now);
System.out.println(s);//2020-1-7
DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS E 是这一年的第D天");
System.out.println(df2.format(now));
}
@Test
public void test07(){
String[] iDs = TimeZone.getAvailableIDs();
for (int i = 0; i < iDs.length; i++) {
String iD = iDs[i];
System.out.println(iD);
}
}
@Test
public void test06(){
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"), Locale.US);
System.out.println(c);
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + c.get(Calendar.HOUR_OF_DAY));
System.out.println("分:" + c.get(Calendar.MINUTE));
}
@Test
public void test05(){
// Calendar c = new Calendar();//Calendar是抽象类,无法直接创建对象
// Calendar c = new GregorianCalendar();//子类名太长,不直接new
Calendar c = Calendar.getInstance();
System.out.println(c);
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
}
@Test
public void test04(){
//Date(int year, int month, int date) 已过时
Date date = new Date(2019,12,31);
System.out.println(date);//Sat Jan 31 00:00:00 CST 3920
/*
int year:是相对于1900年,间隔几年
int month:month - 0-11 的月份
*/
}
@Test
public void test03(){
Date now = new Date();
long time = now.getTime();
System.out.println(time);//1578360704483
}
@Test
public void test02(){
Date now = new Date(Long.MAX_VALUE);
System.out.println(now);//Sun Aug 17 15:12:55 CST 292278994
}
@Test
public void test01(){
Date now = new Date();
System.out.println(now);//Tue Jan 07 09:28:30 CST 2020
}
}
(二)JDK1.8之后的日期时间API
1、为什么要引入新版的API
原来的Date和Calendar有一些问题:
(1)很多API过时
(2)可变性
开发中任意,一个日期时间对象,一旦创建好,就固定代表某个日期时间,不应该可变。
(3)偏移性:
Date中的年份是从1900开始的,而月份都是从0开始的
(4)格式化的支持:格式化只对Date有用,Calendar则不行
(5)此外,它们也不是线程安全的,不能处理闰秒等。
开始要对日期时间API进行改版。
2、Java8新增了很多包和类
- java.time – 包含值对象的基础包
- java.time.chrono – 提供对不同的日历系统的访问。
- java.time.format – 格式化和解析时间和日期
- java.time.temporal – 包括底层框架和扩展特性
- java.time.zone – 包含时区支持的类
3、java.time包中
本地日期时间类型:掌握
LocalDate:表示日期
LocalTime:表示时间
LocalDateTime:表示日期和时间
(1)now:获取系统的日期或时间
(2)of(…):指定日期或时间
(3)plusXxx/withXxx/minusXxx:加上/设置/减去日期或时间,得到新的日期时间对象,原来的日期时间对象不变。
(4)getXxx:获取指定日期和时间值
(5)boolean isLeapYear():判断是否是闰年
4、java.time包中(了解)
ZonedDateTime:获取指定时区和语言环境的日期时间对象
5、java.time包中
日期间隔:Period
时间间隔:Duration
6、java.time.format.DateTimeFormatter
(1)自定义
“yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E 是这一年的D天”
(2)预定义的国际标准
DateTimeFormatter.ISO_DATE_TIME;
(3)长、短、中等的风格
FormatStyle枚举类型:SHORT,LONG,MEDIUM,FULL等
public class Date2 {
@Test
public void test09() {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E 是这一年的D天");
System.out.println(df.format(now));//2020年01月07日 10时45分33秒 910毫秒 星期二 是这一年的7天
DateTimeFormatter df2 = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(df2.format(now));//2020-01-07T10:45:33.91
//FormatStyle枚举类型
DateTimeFormatter df3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
System.out.println(df3.format(now));//20-1-7 上午10:45
DateTimeFormatter df4 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
System.out.println(df4.format(now));//2020年1月7日 上午10时45分33秒
}
@Test
public void test08() {
LocalTime now = LocalTime.now();
LocalTime rest = LocalTime.of(12,0,0);
Duration d = Duration.between(now,rest);
System.out.println(d);//PT1H18M41.421S
}
@Test
public void test07() {
LocalDate today = LocalDate.now();
LocalDate birth = LocalDate.of(2002,6,1);
Period p = Period.between(today,birth);
System.out.println(p);//P-17Y-7M-6D
}
@Test
public void test06() {
ZonedDateTime t = ZonedDateTime.now();
System.out.println(t);//2020-01-07T10:36:26.914+08:00[Asia/Shanghai]
ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(t2);//2020-01-06T21:37:25.433-05:00[America/New_York]
}
@Test
public void test05() {
LocalDate today = LocalDate.now();
System.out.println(today.isLeapYear());
}
@Test
public void test04() {
LocalDate today = LocalDate.now();
System.out.println("年:" + today.getYear());
System.out.println("月:" + today.getMonth());
System.out.println("月:" + today.getMonthValue());
System.out.println("日:" + today.getDayOfMonth());
System.out.println("星期:" + today.getDayOfWeek());
System.out.println("一年的第几天:" + today.getDayOfYear());
}
@Test
public void test03() {
LocalDate today = LocalDate.now();
System.out.println(today);
System.out.println("-------------");
LocalDate future = today.plusDays(130);
System.out.println(future);
System.out.println(today);//不可变对象,修改会产生新对象
}
@Test
public void test02(){
LocalDate today = LocalDate.now();
System.out.println(today);//2020-1-7
LocalDate birth = LocalDate.of(2002,6,1);
System.out.println(birth);
}
@Test
public void test01(){
Calendar c = Calendar.getInstance();//代表当前系统时间
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("--------------------");
c.set(Calendar.YEAR, 2019);
c.set(Calendar.MONTH,11);
c.set(Calendar.DATE,2);
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
}
}
三、和系统相关的API
1、java.lang.System类
(1)System.out.println()
System.out.print()
print()和println()不是System类的API,它是out对象的API,out对象是PrintStream类型。
我们在IO流类中介绍它。
(2)long System.currentTimeMillis()
(3)public static void arraycopy(Object src,int srcPos, Object dest,int destPos, int length) 重要
作用:可以用于复制数组,数组移动元素
第一个参数:Object src:原数组
第二个参数:int srcPos:原数组的起始下标
第三个参数:Object dest:目标数组
第四个参数:int destPos:目标数组的起始下标
第五个参数:int length:一共复制或移动几个元素
当原数组与目标数组不是同一个数组,就相当于复制
当原数组与目标数组是同一个数组,就相当于移动元素
当srcPos > destPos:往左/前移动
当srcPos < destPos:往右/后移动
(4)void System.exit(…):退出JVM
根据惯例,非 0 的状态码表示异常终止。
(5)void System.gc():调用GC回收垃圾。这个方法调用了,不代表GC立刻工作,但是最终会响应。
不建议频繁的手动调用gc()。
(6)String getProperty(String key)
系统属性是:(key,value),根据key获取/设置value,
例如:os.name:表示操作系统类型
…
file.encoding=UTF-8
user.language=zh
file.separator=
os.name=Windows 7
sun.jnu.encoding=GBK
2、java.lang.Runtime:它的对象代表JVM的运行环境
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。
Runtime是单例。(唯一的实例对象)
public class System {
@Test
public void test07(){
Runtime runtime = Runtime.getRuntime();
System.out.println("总内存:" + runtime.totalMemory());
System.out.println("空闲内存:" + runtime.freeMemory());
System.out.println("使用内存:" + (runtime.totalMemory() - runtime.freeMemory()));
}
@Test
public void test06(){
Properties properties = System.getProperties();
System.out.println(properties);
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
System.out.println(entry);
}
// String name = System.getProperty("os.name");
// System.out.println(name);
}
@Test
public void test05() {
int[] arr = {1, 2, 3, 4, 5};
//arr数组移动之前
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//1 2 3 4 5
System.out.println();
System.out.println("---------------");
System.arraycopy(arr,1,arr,0,4);
/*
第一个参数:Object src:原数组 arr
第二个参数:int srcPos:原数组的起始下标 1
第三个参数:Object dest:目标数组 arr
第四个参数:int destPos:目标数组的起始下标 0
第五个参数:int length:一共复制或移动几个元素 4
相当于从arr[0]一共移动了4个元素,arr[1]移动到arr[0]
*/
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//2 3 4 5 5
}
@Test
public void test04() {
int[] arr = {1, 2, 3, 4, 5};
//arr数组移动之前
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//1 2 3 4 5
System.out.println();
System.out.println("---------------");
System.arraycopy(arr,0,arr,2,3);
/*
第一个参数:Object src:原数组 arr
第二个参数:int srcPos:原数组的起始下标 0
第三个参数:Object dest:目标数组 arr
第四个参数:int destPos:目标数组的起始下标 2
第五个参数:int length:一共复制或移动几个元素 3
相当于从arr[0]一共移动了3个元素,arr[0]移动到arr[2]
*/
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//1 2 1 2 3
}
@Test
public void test03(){
int[] arr = {1,2,3,4,5};
int[] arr2 = new int[10];//10个0
System.arraycopy(arr,0,arr2,3,3);
/*
第一个参数:Object src:原数组 arr
第二个参数:int srcPos:原数组的起始下标 0
第三个参数:Object dest:目标数组 arr2
第四个参数:int destPos:目标数组的起始下标 3
第五个参数:int length:一共复制或移动几个元素 3
相当于从arr[0]一共复制3个元素到arr2中,存入arr2[3]开始的三个位置
*/
//arr数组元素不变
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("-------------------------");
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
//0,0,0,1,2,3,0,0,0,0
}
@Test
public void test02(){
long time = System.currentTimeMillis();
System.out.println(time);//1578366364748 距离1970年1月1日凌晨的毫秒值
}
@Test
public void test01(){
System.out.println("输出并换行");
System.out.print("输出不换行");
System.out.print("\n");
System.out.println();//输出换行符
// System.out.print();//错误,print()没有无参
}
}
四、数组的相关算法
(一)回忆:
1、数组的统计(掌握)
偶数个数、素数个数、xx倍数个数…
2、数组的查找(掌握)
(1)顺序查询
3、数组的最值的查找(掌握)
(1)最大/小值
(2)最大/小值的下标
4、排序
(1)冒泡排序(掌握)
public class Array {
@Test
public void test01(){
int[] arr = {1,2,3,4,5};
//反转之前
System.out.println("反转之前:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
System.out.println("--------------------");
//调用反转的方法
// reverse1(arr);
// reverse2(arr);
// reverse3(arr);//失败
arr = reverse4(arr);//重新接受新数组
System.out.println("反转之后:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
//形参:int[] arr
//返回值类型:void ,因为数组是引用数据类型,对形参的反转,相当于对实参的反转
public void reverse1(int[] arr){
//首尾交换
for(int i=0; i< arr.length/2; i++){ //循环次数就是交换次数
//arr[i] 与 arr[arr.length-1-i]交换
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
}
public void reverse2(int[] arr){
//首尾交换
for(int left=0,right=arr.length-1; left < right; left++,right--){
// arr[left] 与arr[right]交换
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
public void reverse3(int[] arr){
//创建一个新数组
int[] newArr = new int[arr.length];
//从arr逆向复制元素到newArr中
for (int i = 0; i < newArr.length; i++) {
newArr[i] = arr[arr.length-1-i];
}
//让arr指向新的newArr
//当arr形参指向新对象/新数组,和原来的实参数组就无关了
arr = newArr;
}
public int[] reverse4(int[] arr){
//创建一个新数组
int[] newArr = new int[arr.length];
//从arr逆向复制元素到newArr中
for (int i = 0; i < newArr.length; i++) {
newArr[i] = arr[arr.length-1-i];
}
return newArr;
}
}
今天再学习
(二)
1、数组的反转
2、数组的扩容
public class Array2 {
@Test
public void test01(){
int[] arr= {1,2,3,4,5};
//扩大arr数组的容量,增加一个元素
arr = grow(arr, arr.length*2);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
/*
形参:int[] arr:代表原数组
int newLength 如果没有第二个参数,那么可以自己选择是增加1个元素,还是扩大为原来的1.5倍或2倍等
返回值类型:int[]
数组本身的长度是不能变的,需要扩容,只增新建一个更大的数组
如果要创建新数组,就需要返回新数组
*/
public int[] grow(int[] arr,int newLength){
//(1)创建新数组
int[] newArr = new int[newLength];
//(2)赋值元素:把原来数组的元素复制到新数组中
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
//(3)返回新数组
return newArr;
}
}
3、数组的插入
public class Array3 {
@Test
public void test01(){
int[] arr = {1,2,3,4,5};
//在arr[1]插入一个元素6
// arr= insert(arr,1,6);
arr= insert2(arr,1,6);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public int[] insert(int[] arr, int index, int value){
//(1)先扩容
int[] newArr = new int[arr.length+1];
//(2)把原数组的元素复制到新数组中
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
//(3)把value值插入到[index]位置
//先将[index]以及后面的元素往右移动
/*
从newArr[index]开始移动,目标数组newArr,把newArr[index]放到newArr[index+1]位置。
假设实际元素的个数5, index=1,移动[1][2][3][4]
[0]~[4]
*/
System.arraycopy(newArr,index,newArr,index+1, arr.length-index);
// 将value值赋值给newArr[index]
newArr[index] = value;
return newArr;
}
public int[] insert2(int[] arr, int index, int value){
//(1)先扩容
int[] newArr = new int[arr.length+1];
//分为三段处理新数组
/*
[0,index]为一部分
[index]为一部分
[index,最后]为一部分
*/
//(2)把原数组的arr[0,index-1]先复制到newArr中
for (int i = 0; i < index; i++) {
newArr[i] = arr[i];
}
//(3)把value值插入到newArr[index]位置
newArr[index] = value;
//(4)把arr[index+1,最后]复制到newArr
for (int i = index; i<arr.length; i++){
newArr[i+1] = arr[i];
}
return newArr;
}
}
4、数组的删除
public class Array4 {
@Test
public void test01(){
int[] arr = {1,2,3,4,5};
//删除arr[1]
delete(arr,1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public void delete(int[] arr,int index){
//(1)把[index+1]后面的元素往前移动
/*
假设arr.length=5,index=1,移动[2][3][4]
*/
System.arraycopy(arr, index+1, arr, index, arr.length-index-1);
//(2)把最后一个位置还原为默认值
arr[arr.length-1] = 0;
}
}
5、数组的查找
(1)顺序查找:遍历数组,挨个比较元素
(2)二分查找,折半查找(必须会手写,笔试题中出现好几次)
要求数组必须是有序的
即无序的数组不能使用二分查找
public class Array5 {
@Test
public void test01(){
int[] arr = {1,2,13,24,24,50,60};
System.out.println(binarySearch(arr,11));
System.out.println(binarySearch(arr,60));
}
public int binarySearch(int[] arr, int value){
int left = 0;
int right = arr.length-1;
int mid = (left + right)/2;
while(left <= right){
if(arr[mid]==value){
return mid;
}else if(arr[mid] > value){
//往左找,修改right
right = mid - 1;
}else if(arr[mid] < value){
//往右边找,修改left
left = mid +1;
}
mid = (left + right)/ 2;
}
return -1;
}
}
6、数组的排序
(1)冒泡排序
(2)直接选择排序
public class Array6 {
@Test
public void test01(){
int[] arr = {49,38,65,97,76,13,27,49};
selectSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+ " ");
}
}
public void selectSort(int[] arr){
/*
每一轮,找出本轮未排序元素中的最小/大值,然后看它是否在它应该在的位置,如果不在,
与它应该在的位置交换。
经过多轮,实现最终排序
例如:{49,38,65,97,76,13,27,49}
第一轮:最小值13,它现在在[5]位置,但是它应该在[0],交换[5]与[0]
{13,38,65,97,76,49,27,49}
第二轮:找出本轮未排序元素中的最小值,13不参与,它已经在正确的位置
最小值27,它现在在[6],但是它应该在[1],交换[6]与[1]
{13,28,65,97,76,49,38,49}
第三轮: 最小值38,它现在在[6],但是它应该在[2],交换[6]与[2]
{13,28,38,97,76,49,65,49}
第四轮: 最小值49,它现在在[5],但是它应该在[3],交换[5]与[3]
{13,28,38,49,76,97,65,49}
第五轮:最小值49,它现在在[7],但是它应该在[4],交换[7]与[4]
{13,28,38,49,49,97,65,76}
第六轮:最小值65,它现在在[6],但是它应该在[5],交换[6]与[5]
{13,28,38,49,49,65,97,76}
第七轮:最小值76,它现在在[7],但是它应该在[6],交换[7]与[6]
{13,28,38,49,49,65,76,97}
*/
//轮数:n-1轮
for (int i=1; i<arr.length; i++){
//(1)先找出本轮未排序部分的最小值及其下标
/*
第一轮i=1:[0,arr.length-1],本轮第一个元素下标为[0]
第二轮i=2:[1,arr.length-1],本轮第一个元素下标为[1]
第三轮i=3:[2,arr.length-1],本轮第一个元素下标为[2]
...
找最小值,假设第一个元素最小,用min与后面的元素一一比较
*/
int min = arr[i-1];
int index = i-1;
for (int j=i; j<arr.length; j++){
if(arr[j] < min){
min = arr[j];
index = j;
}
}
//判断min是否在它应该在的位置
//min应该在本轮第一个元素的位置
if(index != i-1){
//交换arr[index]与arr[i-1]
int temp = arr[index];
arr[index] = arr[i-1];
arr[i-1] = temp;
}
}
}
}
五、JRE的核心类库中有一个数组工具类:java.util.Arrays
1、public static int binarySearch(int[] a, int key):在a数组中查找key是否存在,如果存在返回它的下标,不存在返回负数。
如果不存在,它返回的是“-插入点-1"。插入点是假设这个数存在,它应该在哪个位置。
2、public static int[] copyOf(int[] original, int newLength):根据original数组,复制一个新数组,新数组的长度为newLength,
我们调用时,需要接受新数组
3、public static int[] copyOfRange(int[] original,int from, int to):根据original数组,复制一个新数组,
从original[from]开始复制,如果to超过original的length,那么复制到original最后一个,
如果to在original的合理下标范围内,那么[from,to)
4、public static boolean equals(int[] a,int[] a2):比较两个数组的长度,元素是否相等
5、public static void fill(int[] a, int val):使用val填充a数组
6、public static void sort(int[] a):对基本数据类型的数组实现从小到大排序
…
public static void sort(Object[] a):对对象数组实现从小到大排序,但是要求数组的元素类型必须实现java.lang.Comparable接口
public static void sort(T[] a, Comparator c):对对象数组实现从小到大排序,但是要求指定定制比较器器对象
7、public static String toString(int[] a):将数组a的元素,拼接为一个字符串返回
public class Arrays {
@Test
public void test07(){
int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(arr));
}
@Test
public void test06(){
class Student implements Comparable{
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
@Override
public int compareTo(Object o) {
return this.score - ((Student)o).score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
}
Student[] arr = new Student[3];
arr[0] = new Student("扎告诉你",89);
arr[1] = new Student("贾自强",78);
arr[2] = new Student("刘鑫",90);
// Arrays.sort(arr);
Arrays.sort(arr ,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
return ((Student)o1).score - ((Student)o2).score;
}
});
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] + " ");
}
}
@Test
public void test05(){
int[] arr = {49,38,65,97,76,13,27,49};
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test04() {
int[] arr = new int[3];
Arrays.fill(arr,1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test03() {
int[] arr = {1, 4, 7, 9, 10};
// arr = Arrays.copyOfRange(arr, 2, 10);
arr = Arrays.copyOfRange(arr, 2, 4);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test02() {
int[] arr = {1, 4, 7, 9, 10};
arr = Arrays.copyOf(arr, arr.length * 2);
// arr = Arrays.copyOf(arr, 3);
// arr = copyOf(arr, 10);
// arr = copyOf(arr, 3);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public int[] copyOf(int[] arr, int newLength){
if(newLength < 0){
throw new IllegalArgumentException("数组的长度不能为负数");
}
//(1)创建一个新数组
int[] newArr = new int[newLength];
//(2)从arr赋值元素到newArr
// for (int i=0; i<arr.length && i<newArr.length; i++){
// newArr[i] = arr[i];
// }
int len = arr.length < newLength ? arr.length : newLength;
System.arraycopy(arr,0,newArr,0,len);
//(3)返回新数组
return newArr;
}
@Test
public void test01(){
int[] arr = {1,4,7,9,10};
int value = 8;
int index = Arrays.binarySearch(arr, value);
System.out.println(index);//8如果存在,应该在[3]位置,-3-1=-4
value = 7;
index = Arrays.binarySearch(arr, value);
System.out.println(index);
}
}