java升级(二)数组

数组

定义:

数组是一个简单的复合数据类型,它是一系列有序相同类型数据的集合,可以通过数组名加上一个不会越界下标值来唯一确定数组中的元素。(一个比较特殊的对象,是object的直接子类)在Java中,数组本身就是一个class。数组有很多种初始化的方式,在初始化的时候时刻要记得数组本身是一个对象,通常需要new一个这样的对象才行。一种特殊的情况是类似于这段代码的声明时隐式初始化: Integer[] a = {new Integer(0),new Integer(0),new Integer(0)};    不可以如下: Integer[] a; a = {new Integer(0),new Integer(0),new Integer(0)};

数组和容器类三点区别:

效率、类型限定和对于基本类型的处理,效率肯定是内建的数组效率更高一些。在泛型出来之前,容器类都是存取Object,而数组规定了确定类型。在自动封包解包前,容器类不支持基本类型而数组支持。

public class test {
         int[] a0 = new int[10];
        test t=new test();
        System.out.println("一维数组:" + a0.getClass().getName());
        int[][] a1 = new int[10][10];
        System.out.println("二维数组:" + a1.getClass().getName());
        
           int[][][] a2 = new int[10][10][10];
        System.out.println("三维数组:" + a2.getClass());
        System.out.println(t.getClass());
}
     System.out.println(t.getClass());
}

一维数组:[I;二     维数组:[[I   ; 三维数组:class [[[I   

[代表维度,普通类是路径加类名作为自己的标识,而数组则已[+数组元素路径+类名作为标识,在数组中有一个特征的属性length,数组直接继承自object,object里没有length变量,那么数组如何实现length的

public static void main(String[] args) {
      int a[] = new int[2];
      int i = a.length;
    }
}

M的class文件,打开字节码如下

0 iconst_2                   //将int型常量2压入操作数栈  
    1 newarray 10 (int)     //将2弹出操作数栈作为长度,创建类型为int维度为1的数组,并将数组的引用压入操作数栈  
    3 astore_1              //将数组的引用从操作数栈中弹出,保存在索引为1的局部变量(即a)中  
    4 aload_1               //将索引为1的局部变量(即a)压入操作数栈  
    5 arraylength           //从操作数栈弹出数组引用(即a),并获取其长度(JVM负责实现如何获取),并将长度压入操作数栈  
    6 istore_2             //将数组长度从操作数栈弹出,保存在索引为2的局部变量(即i)中  
    7 return              //m方法返回

这里没有length这个成员变量,arraylength,这条指令是用来获取数组的长度的,JVM对数组的长度做了特殊的处理,它是通过arraylength这条指令来实现的。

数组的应用:

数组要先声明在使用,细节为:声明:数组形式,分配空间:连续存储空间。赋值:数据初始化,基本类型初始值为0,引用类型初始值为null。处理:数据的操作,数组名加有效下标的处理。
数组的性能:数组是一种高效的存储和随机访问对象引用序列的方式。数组在某些地方的使用是不如List和Set集合,数组有自己的优势,集合的底层也是通过数组来实现的。比如在求和的使用中使用数组和list的对比。数组使用get函数获取数据,list使用get()函数。list.get(i)这个动作里进行了拆箱操作,Integer对象对int型数据进行对象封装,这里拆箱和数组获取相比慢了很多。

数组的操作

数组的长度:数组生明后长度不会改变,但是如果想让其改变,模拟arraylist的扩容方法,将原始数组拷贝至新数组中,新数组的长度时原数组的1.5倍。

数组的复制:使用List.toArray()方法转换成数组然后再通过Arrays.copyOf拷贝,再转换成集合,若数组元素为对象,则数组里面数据是对象引用,典型浅复制。

数组转换为list,Arrays的工具里有asList()方法,将其转化成列表

public static void main(String[] args) {
        int[] a = new int[]{1,2,3};
        List list = Arrays.asList(a);
        System.out.println(list.size());
 }

结果是1而不是3,在asList()的源码中T..a参数是泛型变长参数,这里没有报错是因为,数组是对象处理的可以是泛型

public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }

程序是把一个int型的数组作为了T的类型,所以在转换之后List中就只会存在一个类型为int数组的元素了。所以我们这样的程序System.out.println(datas.equals(list.get(0)));输出结果肯定是true。当然如果将int改为Integer,则长度就会变成3了。

java的Arrays()方法

Arrays提供了丰富的方法,包括sort和binarySearch(数组有序下二分查找)。而sort方法中的排序算法大致是这样一个思路,分类型+分数组长度。Arrays的sort方法针对7个基本类型的数组和Object以及泛型T数组分别给出了多种不同的重载实现。基本类型数组,对于数组长度较短的使用插入排序,而对于长度较大的基本都采用了经过改进的快速排序算法。

对象类型排序,对于短数组一样采用了插入排序,而较长的数组则使用了归并排序。对基本类型和对象类型排序算法的不同(可能是算法的稳定性)快速排序是不稳定的算法,而这对基本类型没什么影响,对于对象类型则不然,故采取了稳定的归并排序算法。较短和较长数组的区分,Arrays里的方法实现设定了一些特定的阈值常量。对于float和double浮点排序,排序算法做了一些特殊处理,进行了排序初始化处理。Java中的八大基本类型,除了boolean,其它七种都是可以且有需求进行排序的,如果一个数组是单一的基础类型,形如int[] data, long data[]都可以直接使用Arrays.sort()进行排序。对于所有可排序的基本类型,都是采用DualPivotQuicksort来进行排序的多路归并思想是:元素个数从1-47,则直接使用插入排序进行排序。元素个数从47-286,则使用多路快速排序。元素个数大于286,则使用归并排序。快排是一个中轴两个指针移动,一次排序划分两部分以中轴为界。

对路快排。1、选取两个中轴P1, P2,假设P1<P2,否则交换。2、过程中原数组会分为四个部分:小于中轴1,大于中轴2,介于两个中轴之间,未排序部分(刚开始除了两个中轴,其它元素都属于这部分)。3、开始后,从未排序部分选取一个数,和两个中轴作比较,然后放到合适的位置,一直到未排序部分无数据,结束一趟排序。4、递归地处理子数组,稳定排序,时间复杂度稳定为O(nlogn)。

引用类型的排序可以用ComparatorComparable

参数ComparableComparator
排序逻辑排序逻辑必须在待排序对象的类中,故称之为自然排序排序逻辑在另一个实现
实现实现Comparable接口实现Comparator接口
排序方法int compareTo(Object o1)int compare(Object o1,Object o2)
触发排序Collections.sort(List)Collections.sort(List, Comparator)
接口所在包java.lang.Comparablejava.util.Comparator

Comparator:强行对某个对象collection进行整体排序的比较函数,可以将Comparator传递给Collections.sort或Arrays.sort。接口

/** 
  * @return o1小于、等于或大于o2,分别返回负整数、零或正整数。 
  */  
 int compare(Object o1, Object o2);  

强行对实现它的每个类的对象进行整体排序,实现此接口的对象列表(和数组)可以通过Collections.sort或Arrays.sort进行自动排序。接口:int compareTo(object o)实例:

public class User {
	private String id;
	private int age;
	public User(String id, int age) {
		this.id = id;
		this.age = age;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
}

Comparable的实现

import java.util.Arrays;
public class User implements Comparable {
	private String id;
	private int age;

	public User(String id, int age) {
		this.id = id;
		this.age = age;
	}
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public int compareTo(Object o) {
		return this.age - ((User) o).getAge();
	}

	public static void main(String[] args) {
		User[] users = new User[] { new User("张三", 23), new User("李四", 21) };
		Arrays.sort(users);
		for (int i = 0; i < users.length; i++) {
			User user = users[i];
			System.out.println(user.getId() + " " + user.getAge());
		}
	}
}

Comparator对User集合实现:

import java.util.Arrays;
import java.util.Comparator;
public class UserComparator implements Comparator {
	public int compare(Object o1, Object o2) {
		return ((User) o1).getAge() - ((User) o2).getAge();
	}
	public static void main(String[] args) {
		User[] users = new User[] { new User("张三", 23), new User("李四", 21) };
		Arrays.sort(users, new UserComparator());
		for (int i = 0; i < users.length; i++) {
			User user = users[i];
			System.out.println(user.getId() + " " + user.getAge());
		}
	}
}

结果:李四:21 张三:23

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值