前提提要:代码块中均为伪代码,不是正式规格代码,只是为了方便大家观看方便易解,有错误请指正
【Array数组的方法】
先导包:【import java.util.*;】或者【import java.util.Arrays;】(解释:*在正则表达式表示“所有”,也即导入Java的util里的所有的包)
1、【Array数组】转成【字符串】
Arrays.toString(array)
(前面笔记提过: 【基本类型数据】转【字符串】——>“String.valueOf(数据)”
【引用类型数据】转【字符串】——>“数据的包装类.toString()” )
这里Array就是【引用数据类型】,因为它是【new出来】的(例子:int[] a = new int[10]; double[] a = new double[10]; String[] a = new String[10]......),【new出来】的就是引用数据类型,是变量【地址值】而不是【值本身】
所以Array用的就是Array.toString()
例子:
int[] num1 = {1,2,3,4,5};
doule[] num2 = {1.2,2.4,5.23};
String s1 = Arrays.toString(num1); ——————> [1,2,3,4,5]
String s2 = Arrays.toString(num2); ——————> [1.2,2.4,5.23]
【另外返回【多维数组】为字符串是:Arrays.deepToString(array)】
例子:
int[][] num = {{1,2,3,4,5},{12,24,523}};
String s = Arrays.deepToString(num); ——————> [[1, 2, 3, 4, 5], [12, 24, 523]]
2、【Array数组的排序】
Array数组的【默认升序】(Array的API类原来发明者制定的默认就是升序)
(1)Arrays.short(array)
例子:
int[] num = {3,5,2,1,4};
String[] str = {"cc","bb","ee","aa","ff","dd"};
Array.sort(num); ——————> {1,2,3,4,5}
Array.sort(str); ——————> {"aa","bb","cc","dd","ee","ff"}
(Array.sort()方法的返回值是void,直接改完原数组的排序,不用接收返回;另外字母是按照ASCII码排的序)
(2)Arrays.parallelSort(array)
对数组元素进行排序(并行排序),当数据规模较大时,会有更好的性能,一样的用法和效果
int[] num = {3,5,2,1,4};
Array.parallelSort(num); ——————> {1,2,3,4,5}
3、Array数组的【区间升序】(还是刚刚的方法,只是只调部分,比如有的时候这个数组只有一小部分乱就不用整个排序)
Arrays.short(array,起始位置,末尾位置+1)
例子:
int[] num = {3,1,2,4,5,6,7,8,9};
Array.sort(num,0,3); ——————> {1,2,3,4,5,6,7,8,9}
(这里数组只有“3,1,2”前三位是乱的,那就改这部分)
4、Array数组的【降序】
【Arrays.sort(Array, (x,y) -> y-x);】
或者【Arrays.sort(Array,Collections.reverseOrder());】
或者【实现comparator接口并重写compare()方法】
(注意!!!既然原来没有Array的short方法默认升序,没有降序,那这就相当于我们自己改了方法,这里排序就对数组里的成员是【基本类型数据】不管用了,虽然【数组】是【引用数据类型】,但是【内部成员】不是啊)
(那么要进行改造:【基本数据类型成员】的数组————>【包装类成员】的数组,
或者说把【原数组】的【基本类型数据】————>变成【包装类】)
-----------------------------------------------------------------------------------------------------------
【这里拓展一下】8种基本数据类型对应的包装类:
字节型byte:Byte
短整型short:Short
整型int : Integer
长整型long :Long
字符型char:Character
布尔型boolean: Boolean
浮点型float:Float
浮点型double:Double
(其中需要注意【int】对应的是【Integer】,【char】对应的【Character】,其他6个都是基本类型【首字母大写】即可。)
(另外单个包装类跟基本数据类型还可以自动【装箱】【拆箱】,【装箱】理解就是直接定义声明,【拆箱】理解就是包装类定义的变量)
例子:
Integer i = 2; //正常应该是Integer i = new Integer(2);
int a = i - 2; //正常应该是int a = Integer.valueOf(i) - 2;
System.out.print(a); ——————> 正常输出 a=0
-----------------------------------------------------------------------------------------------------------
~那有人会犯贱问了:你这改的是单个数据啊,只能把一个数据改为包装类,那我一开始设一个“【基本数据类型成员】的数组”,那要怎么把整个数组变成“【包装类成员】的数组”??
用循环换啊。。。。
例子:
char[] a = {'a','b','c'};
Character[] A = new Character[3];
for(int i=0; i<a.length; i++){
A[i] = Character.valueOf(a[i]);
——————> 现在就成了每个成员都是Character类型的{'a','b','c'}
}
~又有人要犯贱问:那我还要换来换去这么麻烦,还不如直接自己写一个方法排序,能不能一开始就设“【包装类成员】的数组”??
例子:
Integer[] num = {1,2,3,4,5,6,7,8,9}; ——————> 现在每个成员都是Interge类型的{1,2,3,4,5,6,7,8,9},跟正常定义数组一样
然后现在调升序就简单了,直接Arrays.sort(num, (x,y) -> y-x);
例子1:
char[] a = {'a','b','c'};
Character[] A = new Character[3];
for(int i=0; i<a.length; i++){
A[i] = Character.valueOf(a[i]); ——————> 现在就成了每个成员都是Character类型的{'a','b','c'}
}
Arrays.sort(A, (x,y) -> y - x);
for(Character i:A){
System.out.print(i+" "); ——————> 现在这【字符数组】的排序就是【降序】{'c','b','a'}
}
//下面这样就会直接报错,因为char类型不能用Arrays.sort(a, (x,y) -> y - x);降序
// char[] a = {'a','b','c'};
// Arrays.sort(a, (x,y) -> y - x);
// for(Character i:a){
// System.out.print(i+" ");
// }
例子2:
Integer[] num = {1,2,3,4,5,6,7,8,9}; ——————> 现在每个成员都是Interge类型的{1,2,3,4,5,6,7,8,9},跟正常定义数组一样
Arrays.sort(num, (x,y) -> y - x);
for(Integer i:num){
System.out.print(i+" "); ——————> 现在这【数字数组】的排序就是【降序】{9,8,7,6,5,4,3,2,1}
}
//下面这样就会直接报错,因为int类型不能用Arrays.sort(num, (x,y) -> y - x);降序
//int[] num = {1,2,3,4,5,6,7,8,9};
//Arrays.sort(num, (x,y) -> y - x);
//for(int i:num){
// System.out.print(i+" ");
//}
也可以写成这样(更推荐)
Integer[] num = {1,2,3,4,5,6,7,8,9}; ——————> 现在每个成员都是Interge类型的{1,2,3,4,5,6,7,8,9},跟正常定义数组一样
Arrays.sort(n, (x,y)->Integer.compare(y,x) );
for(Integer i:num){
System.out.print(i+" "); ——————> 现在这【数字数组】的排序就是【降序】{9,8,7,6,5,4,3,2,1}
}
还有一个函数可以作为参数传入,自动排序后再返回降序:Collections.reverseOrder()
例子:
Integer[] num = {1,2,3,4,5,6,7,8,9};
Arrays.sort(num,Collections.reverseOrder());
for(Integer i:num){
System.out.print(i+" "); ——————> 一样的效果:{9,8,7,6,5,4,3,2,1}
}
当然,有些人不明白为什么前面那些写法可以那么写,很抽象,这里做一解释:
( x , y ) -> x - y这种形式叫【lambda表达式】,用于简写【匿名局部类】,很像JavaScript里的“箭头函数”,具体格式为:
//正常的写法:
//假设MyInterface是一个“匿名内部实现类”,可以写成:
MyInterface myinterface = new MyInterface(){
@Overide
public void xxx(x,y){
//执行某事
}
}
//lambda简洁写法:
MyInterface myinterface = (x,y) -> public void xxx(x,y){
//执行某事
}
//那么如果这个方法体里只有一句代码,那就可以直接省略写成这样:
MyInterface myinterface = (x,y) -> 方法体里的一行执行代码
//如果只有一句return返回,也是一样,连return都不用写
MyInterface myinterface = (x,y) -> 要return的表达式
//如果是空参,那么别漏了空括号
MyInterface myinterface = () -> 要干啥
那么现在来看( x , y ) -> y-x的意思就是:
//原来的匿名局部类
new Comparator<Integer>(){
@Override
public int compare(Integer x,Integer y){
return y-x;
}
}
//而变成
(x , y) -> public int compare(Integer x,Integer y){
return y-x;
}
//再简化变成:
(x , y) -> return y-x;
//最后最简化:
//而变成
(x , y) -> y-x;
当然如果还是觉得难以理解,那还有一种方法,那就是自己重写一下排序方法
详细分析一下:
【Array.sort()原理】
1、Arrays(一个参数),这种形式就是Arrays的sort方法就是根据【Comparable】接口的【compareTo】方法来判断排序,不重写改变这个【comparaTo】方法的话就是正常自然升序排序;如果按照自己的需求实现【Comparable】接口并重写它的【comparaTo】方法,就可以改成降序,Arrays.sort()方法会自动判断
2、Arrays(参数1,参数2),这种形式,参数1就是【泛型类型】,然后参数2就必须是【实现comparator接口的实现类】,就是直接在参数2的位置写一个实现comparator接口的匿名局部类
具体是怎么调用【comparator接口】或者【comparable接口】操作的,不需要了解太多,我查了一星期都差不明白
然后大概的原理是,当【Array.sort()】遍历所有数并分别传给【comparator<T>接口的实现类的compara()方法】或者【comparable的实现类的compareTo()方法】去互相进行比较时,1、当返回【正数】时执行【交换顺序】 2、当返回【0】时不执行操作 3、当返回【负数】时也不执行操作
切记,真别去查Array.sort()是怎么排序的,操了N多个排序,它会自动根据给的数选择高效的排序方法,我们不需要知道具体怎么排序,只需要知道什么时候会执行排序就行
第一种方法:
【comparator<T>】的【compare(参数1,参数2)】方法
comparator<T>有两个方法:【compare(参数1,参数2)】和【equals(参数)】,基本java.lang包的类String、Arrays...这些类都实现了这个接口并重写了里面的方法
然后【comparator<T>】这里的参数T是【泛型】,也就是跟ArrayList<T>一样,不能用int、double、char...这种基本数据类型,只能用【泛型】,或者说是【包装类】跟【对象】
然后这个接口里面的【compare(参数1,参数2)】方法,具体形式是:public int compare(参数1,参数2),用来比较两个数————>【参数1 > 参数2,返回正数】
【参数1 = 参数2,返回0】 【参数1 < 参数2,返回负数】
具体比较逻辑是:
public int compare(参数1,参数2){
if( 参数1 - 参数2 > 0 ){
return 1;
}else if( 参数1 - 参数2 == 0 ){
return 0;
}else{
return -1;
}
}
或者:
public int compare(参数1,参数2){
return (参数1 - 参数2)>0 ? 1 : ((参数1 - 参数2) == 0 ? 0 : -1);
}
或者更简单:
public int compare(参数1,参数2){
//左边大,减完结果不就是正数吗?
return 参数1 - 参数2; //一样大不就是0吗?
//小的话不就是负数吗?
}
然后要去用【匿名局部类】去【实现】【comparator<T>接口】,这个【匿名局部类】就是参数2直接传到Arrays(参数1,参数2),
然后直接这个【匿名局部类】里,【重写】【compare(参数1,参数2)】方法,就可以达到自己想要的排序方式,(以上括起来的【专业名称】不知道是啥的,去查往期【面向对象三个特点:封装、继承(抽象—>接口)、多态】知识点)CSDNhttps://mp.csdn.net/mp_blog/creation/editor/134676284
具体例子:
import java.util.Arrays; ————> 切记【Arrays】不是java.lang包里的,要导包才能用
import java.util.Comparator; ————> 切记【Comparator】不是java.lang包里的,要导包才能用
public class Array_排序的方法 {
public static void main(String[] args){
Integer[] a = {1,3,8,2,10};//定义一个包装类乱序数组
Arrays.sort(a,new Comparator<Integer>(){ ————> 一个【匿名局部类】来实现【comparator<T>接口】,注意Comparator是大写C
@Override
public int compare(Integer x,Integer y){ ————> 【重写】compare()方法
return y-x;//返回值取反,就会得到和升序相反的结果,也就是【降序】
}
});
for(int i:a){
System.out.print(i+" "); ————> 降序:10、 8、 3、 2、 1
}
}
}
第二种方法:
【comparable】的【compareTo(参数1,参数2)】方法
记住区别,前面comparator的compare()是直接应用于Arrays.sort()的含两个参数情况的第二个参数里的;现在讲的这个方法是1、先写一个继承comparable的实现类,2、然后根据自己需要重写compareTo()方法,3、注意comparaTo()返回给Arrays.sort()的返回值是int!
例子1:
import java.util.*;
public class test {
public static void main(String[] args){
MyComparable num1 = new MyComparable(1);
MyComparable num2 = new MyComparable(3);
MyComparable num3 = new MyComparable(8);
MyComparable num4 = new MyComparable(2);
MyComparable num5 = new MyComparable(10);
MyComparable[] a = {num1,num2,num3,num4,num5};//一个对象类乱序数组
Arrays.sort(a);
for(MyComparable i:a){
System.out.print(i.x+" ");
}
}
}
class MyComparable implements Comparable<MyComparable>{
int x;
MyComparable(int x) {
this.x = x;
}
@Override
public int compareTo(MyComparable o){
return o.x - this.x;
}
}
例子2(一道PTA的题目):
import java.util.*;
public class Main{
public static void main(String[] args) {
Employee[] E = new Employee[5];
E[0] = new Employee(1, 500, 400, "职工1", "female");
E[1] = new Employee(3, 600, 300, "职工3", "male");
......省略
//1、第一种自定义排序方法:重写comparable接口的compareTo方法
Arrays.sort(E);//Arrays.sort()方法会自动找到重写的的这个方法自动排序
for (int i=0 ;i<E.length; i++) {
System.out.println(...输出排序结果);
}
//2、第二种自定义排序方法:直接在Arrays.sort()方法传入第二个参数,这个参数就是重写comparator接口的compare方法
Arrays.sort(E, new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return o1.getTeamScore() - o2.getTeamScore();
}
});
}
//用自定义的员工Employee类实现Comparable<T>接口,这里<>里面传对象
static class Employee implements Comparable<Object> {
......省略
//重写改写compareTo方法
@Override
public int compareTo(Object o) {
//用【instanceof】判断这个传进来的对象是不是Emploee
if (o instanceof Employee) {
Employee e = (Employee) o;//是的话就把它强制类型转化成Employee
return e.团体险业绩 - this.团体险业绩;
}
return o.团体险业绩 - this.团体险业绩;
}
}
}
显然大家能看到一个缺陷,这个方法更适合对象自定义的排序,普通的数组就没必要了,因为它只能用于对象
5、查找Array数组的【某个成员】的【下标】(没找到就返回-1)
Arrays.binarySearch(Array,某个成员);
(注意!!!因为这个方法是按照“二分法”查找的,所以这个数组必须【先】排好【升序】,然后再用Arrays.binarySearch()查找
例子:
// 这样报错误答案,因为还没有排序,乱序做二分查找就错了
// Integer[] num = {1,8,3,4,7,6,2,5,9};
// int index = Arrays.binarySearch(num, 3);
// System.out.println(index); ——————> 返回错误答案:-2
// 这样才对
Integer[] num = {1,8,3,4,7,6,2,5,9};
Arrays.sort(num);
int index = Arrays.binarySearch(num, 3);
System.out.println(index); ——————> 2,对了
6、Array数组复制给别的数组
(1)Arrays.copyOf(被复制的Array,长度);
(这是老方法:只能固定复制下标0到指定位置的成员,而且可能会改变新数初始化的长度)
例子:
int[] arr1 = {1, 2, 3};
int[] arr2 = new int[3]; ——————> 注意这里我初始化新数组就3个单位长
arr2 = Arrays.copyOf(arr1, 5); ——————> 这里我让新数组复制的长度为5,变成了{1,2,3,0,0}
(2)Arrays.copyOfRange(被复制的Array,起始位置,末尾位置+1);
(这是改进版新方法:可以指定只复制区间成员)
例子:
int[] arr1 = {1, 2, 3, 4 , 5 , 6};
int[] arr2 = Arrays.copyOfRange(arr1,0,3); ——————> {1,2,3}
7、Array填满整个数据一个值的办法
Arrays.fill(Array,要填的数据)
为什么会有这个方法呢?不知道,可能有一天发明他的程序员疯了:“卧槽!毁灭吧!”然后把所有算了一个月的数组的值全部变成一个值,比如:shit,然后输出,他就爽了。。。我瞎掰的
例子:
String[] s = {"我很开心","我爱老板","我爱工作","上班快乐"};
Arrays.fill(s,"我发疯了!");
System.out.println(Arrays.toString(s)); ——————> [我发疯了!, 我发疯了!, 我发疯了!, 去我发疯了!]
8、比较两个一维数组是否一样【跟Array.sort一样贼鸡儿有用高效卧槽】
Arrays.equals(array1,array2)
.equalOf() 和.equals()这两个API方法很像、都适用于引用类型数据,所以String和Array用它们比较
但是有点小区别是String是直接用另一个字符串跟自己比较:
s1.equalOf(s2) //注意:equalOf不是equals ————> 【简单理解String自己跟别人比较,
而Array是找老大Arrays统一比较它两
用Array类括号里传两个array数组比较它两:
Arrays.equals(array1,array2) //注意:是equals不是equalOf
例子:
int[] a = {1,2,3,4,5};
int[] b = {1,4,7,9,2};
System.out.print(Arrays.equals(a,b)); ——————> false
9、比较两个多维数组是否一样【更吊】
Arrays.deepEquals(array1,array2)
例子:
int[][] a = {{1,2,3,4,5},{1,4,7,9,2}};
int[][] b = {{1,2,3,4,5},{1,4,7,9,2}};
System.out.print(Arrays.deepEquals(a,b));; ——————> true