数组是具有相同数据类型的一组数据的集合,java语言中将数组视为对象,数组没有专门的类型定义,一旦定义,长度不可变,成员统一,java.util.Arrays类用来管理数组;比如:排序,查找,比较等。
一. 数组的定义(主要是一维数组)
1.静态定义
如:
int[] a = {1,2};
Student[] s = {new Student),new Student()};
2.动态定义
如:
int[] a = new int[10];
Student[] s = new Student[10];
二.数组的内存分配
1.虽然基本数据类型不是对象,但基本数据类型构成的数组是对象,所以内存分配(一维数组)如图:
2.一维对象数组内存分配
三.多维数组
多维数组可以看作一个按照行和列存储的内存空间。二维数组的行上的元素个数可以不同但列上的元素必须相同。
int[][] a = new int[5[];
注意:数组长度是length属性,而字符串长度是length()方法
四.java.util.Arrays
此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。 除非特别注明,否则如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException。
1.asList(T... e)
在源代码中此方法是这样定义的:
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}
.
.
.
}
注意:asList方法返回的是Arrays类的静态私有内部类java.util.Arrays$ArrayList不是java.util.ArrayList,
这两个类都是继承自抽象类AbstractList,AbstractList中的Add(E e)方法实现调用 add(size(), e),
除非重写 add(int index, E element)否则此实现将抛出
UnsupportedOperationException
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
.
.
.
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
.
.
.
}
java.util.ArrayList中重写了add(int,E)方法,而java.util.Arrays$ArrayList没有重写add(int,E)方法,所以 就运行到AbstractList中的Add(T... a)方法抛出UnsupportedOperationException异常,即asList(E element)返回的ArrayList不能增加元素,同理也不可删除元素!若对此list增删操作必须转换为java.util.ArrayList
User[] u = {new User(),new User(),new User()};
Lise<User> users = Arrays.asList(u);
ArrayList list = new ArrayList(users);
数组u中的元素在内存中的地址同users 和list中的对象在内存中的地址相同,所以修改list.get(0)中的User,users.get(0)和u[0]中的内容同样会变!
那么源代码中为什么用内部类java.util.Arrays$ArrayList而不使用java.util.ArrayList将数组直接转换为链表呢?先做下面这样的测试
public static void main(String[] args)
{
//定义长度为100的对象数组str
String[] str = new String[100];
//为str数组赋值
for(int i=0;i<100;i++)
{
str[i] = "str"+i;
}
//得到转化前的时间
long a = System.currentTimeMillis();
//List<String> list=null;
for(int i=0;i<1000;i++)
{
for(int j=0;j<1000;j++)
{
// list= Arrays.asList(str);
AsList_ArrayList.asList(str);
}
}
//ArrayList<String> l = new ArrayList<String>(list);
//得到转化后的时间
long b = System.currentTimeMillis();
System.out.println(b-a); //我的机子上输出为6844
}
上面是用自定义的静态方法(如果有更好的转换方法,请指出)将数组转换为ArrayList,效率比较低。下面是调用系统中的asList方法
public static void main(String[] args)
{
//定义长度为100的对象数组str
String[] str = new String[100];
//为str数组赋值
for(int i=0;i<100;i++)
{
str[i] = "str"+i;
}
//得到转化前的时间
long a = System.currentTimeMillis();
List<String> list=null;
for(int i=0;i<1000;i++)
{
for(int j=0;j<1000;j++)
{
list= Arrays.asList(str);
}
}
ArrayList<String> l = new ArrayList<String>(list);
//转化后的时间
long b = System.currentTimeMillis();
System.out.println(b-a); //我的机子上输出为64
很显然两段代码在运行效率上相差很大,所以我想系统使用静态内部类主要是性能上的考虑,这种设计方法值得学习。
2.java.util.Arrays.binarySearch()
3.java.util.Arrays.copeOf()
4.java.util.Arrays.copeOfRange()
5.java.util.Arrays.equals()
6.java.util.Arrays.fill()
7.java.util.Arrays.hashcode()
5.java.util.Arrays.sort()