一、ArrayList使用
1.ArrayList概述
java.util.ArrayList类就是传说中的动态数组,相当于Array的复杂版本。也就是说,ArrayList对象既有数组的特征,也有列表的特征。ArrayList实现了List接口,ArrayList是最常用的List实现类,内部是通过数组实现的,允许对元素进行快速随机访问,可以动态添加或删除元素。
在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,Vector默认增长为原来一倍,而ArrayList却是原来的50%,有利于节约内存空间。
大家知道,数组是静态的,数组被初始化之后,数组长度就不能再改变了,而ArrayList是可以动态改变大小的。
①数组和集合的区别:数组可以存储基本数据类型和对象,长度是固定的,且只能存储相同类型的元素;而集合只能存储对象,长度是可变的,可以存储不同类型的对象。
②那么什么时候使用Array,什么时候使用ArrayList?答案是:当我们不知道到底有多少个数据元素的时候,就可使用ArrayList;如果知道数据集合有多少个元素,就用数组。
2.ArrayList常用方法
下面总结了一些比较常用的ArrayList类成员方法:
①构造函数
ArrayList<String> strList = new ArrayList<>(); 创建一个空的数组列表,用来存放String类型的对象
②增加元素到列表中
boolean add(Element e) 增加指定元素到列表尾部.
void add(int index, Element e) 增加指定元素到列表指定位置.
addAll(ArrayList aList) 将指定集合中的所有元素添加到本集合中
③从列表中删除元素
void clear() 从列表中删除所有元素.
E remove(int index) 删除列表中指定位置的元素.
protected void removeRange(int start, int end) 删除表中从某一个位置开始到某一个位置结束的元素
④获取列表中的元素
E get(int index) 获取列表中指定位置处的元素.
⑤修改某个元素
E set(int index, E element) 将列表中指定位置上的元素替换成新元素
⑥搜索元素
boolean contains(Object o) 如果列表包含指定元素,返回true
int indexOf(Object o) 返回元素在列表中第一次出现的位置,如果返回-1,表示列表中没有这个元素
int lastIndexOf(Object o) 返回元素在列表中最后一次出现的位置,如果返回-1,表示列表中没有这个元素
⑦检查列表是否为空
boolean isEmpty() 返回true表示链表中没有任何元素
⑧获取列表大小
int size() 返回列表长度(列表包含元素的个数).
⑨将列表转换为一个数组
Object[] toArray() 获取一个数组,数组中所有元素是列表中的元素
3.Collections
Collections是集合框架中的工具类,里面定义的都是静态方法。提供的方法中有可以对list集合进行排序,逆转顺序,二分查找等方法。通常常用的集合都是线程不安全的,因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
如何实现ArrayList的反转排序?
用Collections.reverse(List list)即可:
List<String> list = Arrays.asList(new String[] {"aa", "bb", "cc", "dd", "ee"});
Collections.reverse(list);
for(String string : list)
System.out.println(string);
常用方法:
①排序操作(主要针对List接口相关)
reverse(List list):反转指定List集合中元素的顺序
shuffle(List list):对List中的元素进行随机排序(洗牌)
sort(List list):对List里的元素根据自然升序排序
sort(List list, Comparator c):自定义比较器进行排序
swap(List list, int i, int j):将指定List集合中i处元素和j处元素进行交换
rotate(List list, int distance):将所有元素向右移位指定长度,如果distance等于size那么结果不变
②查找和替换(主要针对Collection接口相关)
binarySearch(List list, Object key):使用二分搜索法,以获得指定对象在List中的索引,前提是集合已经排序
max(Collection coll):返回最大元素
max(Collection coll, Comparator comp):根据自定义比较器,返回最大元素
min(Collection coll):返回最小元素
min(Collection coll, Comparator comp):根据自定义比较器,返回最小元素
fill(List list, Object obj):使用指定对象填充
frequency(Collection Object o):返回指定集合中指定对象出现的次数
③同步控制
Collections工具类中提供了多个synchronizedXxx方法,该方法返回指定集合对象对应的同步对象,从而解决多线程并发访问集合时线程的安全问题。HashSet、ArrayList、HashMap都是线程不安全的,如果需要考虑同步,则使用这些方法。这些方法主要有:synchronizedSet、synchronizedSortedSet、synchronizedList、synchronizedMap、synchronizedSortedMap。
4、List和ArrayList如何选用?
List是一个接口,不能被实例化。其实现了Collection接口,拥有Collection的常用方法,也扩展了自己作为列表类型所特有的方法。
ArrayList是List接口的实现类,可以new ArrayList()构造对象,在List基础上扩展了一些实用功能。
List list = new ArrayList();//对的,这句创建了一个ArrayList的对象然后上溯到了List。此时它是一个List对象了,有些ArrayList特有但是List没有的属性和方法,它就不能再用了。
为什么要用 List list = new ArrayList(),而不用 ArrayList alist = new ArrayList()呢?
问题就在于List有多个实现类,现在你用的是ArrayList,也许哪一天你需要(为了线程安全/节约内存空间等)换成其它的实现类,如LinkedList或者Vector等等,这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。
假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了ArrayList特有的方法和属性
巨坑:List的subList()方法生成的表只是原表的视图,实际上还是对原表的操作,慎用!
5、ArrayList和LinkedList如何选用?
ArrayList用数组存储元素,访问元素快,占内存;LinkedList用链表存储元素,节约内存空间,查询速度稍慢。
如果除了在末尾外不能在其他位置插入或者删除元素即主查询,那么ArrayList效率更高,如果需要经常插入或者删除元素,就选择LinkedList。
——ArrayList 线程不安全,查询速度快
——LinkedList 链表结果,增删速度快
二、Array使用
1.Array概述
①Java中的数组,是一种简单的线性数据存储结构,用来存储固定大小的同类型元素。可以存储基本数据类型和对象,但长度是固定的。数组对象中的length常量保存了数组的长度,并且是public常量可以直接引用。
②其用牺牲自动扩展大小来换取与集合相比的唯一优势——查询效率的提升。它本身是一种引用类型的数据,所以我们要使用数组就要首先声明和初始化,而它初始化的完成也就意味着此数组的大小将不再改变。
③数组的引用存放在栈内,实际数组对象存放在堆内存中。
④数组索引总是以0开始,具有N个值的数组索引为:0—(N-1),其中N = array.length
⑤数组的元素是通过索引访问的,数组名[索引值],如num[8]访问数组num中的第9个值。
⑥索引运算符自动执行数组边界检查,保证引用一个数组元素的索引值在有效范围内索引值必须大于等于0,小于数组长度,否则会抛出ArrayIndexOutOfBoundsException。
2.Array声明与初始化
①声明数组变量引用,必须指明数组大小
a) type[] arrayName; exp: String[] strArray = new String[5];
b) type arrayName[]; exp: String strArray[] = new String[5]; //源于C的写法,易造成混淆,所以基本很少用
②数组的初始化有两种:
a.静态初始化——数组大小由系统分配,我们只为数组每个位置上赋值
String[] strs = new String[]{"sdsaf","fsdss","5552"};
b.动态初始化——只指定数值的大小,初始化工作由系统为我们完成(即为数组的每个位置赋初始值)
String[] strArray3 = new String[5];//此时String数组的每个位置上的值都由系统来初始化、使用默认的值
//我们能做的是动态的为strArray3每个位置上的值进行修改
for (int i = 0; i < strArray1.length; i++) {
//这里仅用原始的方法进行赋值。
strArray3[i] = strArray1[i];
}
3.多维数组
①多维数组本质是一维数组的延伸,多维数组可以看成是数组的数组。比如二维数组就是一个特殊的一维数组,其每个元素都是一个一维数组,不要求二维数组每一维的大小相同。
②多维数组的动态初始化(以二维数组为例)
a.直接为每一维分配空间,格式如下:
type[][]arrayName =newtyp[rowLength][colLength];
b.type可以为基本数据类型和复合数据类型,rowLenght和 colLenght必须为正整数,rowLength为行数,colLength为列数,例如:
inta[][] = newint[2][3];
解析:二维数组 a 可以看成一个两行三列的数组。
c. 从最高维开始,分别为每一维分配空间,例如:
Strings[][] = newString[2][];
s[0] = newString[2];
s[1] = newString[3];
s[0][0] = newString("Good");
s[0][1] = newString("Luck");
s[1][0] = newString("to");
s[1][1] = newString("you");
s[1][2] = newString("!");
③多维数组元素的访问
对二维数组中的每个元素,引用方式为arrayName[rowIndex][colIndex],例如:s[1][0],访问第第二行第一列的元素"to"
4.数组工具类Arrays
数组倒序实现:
/*
* 整数数组倒序
*/
public class ArrayReverse
{
public static void main(String[] args)
{
int[] nums= {1,2,3,4,5};
for(int i : nums)
{
System.out.print(i+" ");
}
System.out.println("\n");
nums = ArrayReverse.reverse(nums);
for (int i : nums)
{
System.out.print(i+" ");
}
}
public static int[] reverse(int[] arr)
{
int[] result = new int[arr.length];
for(int i = 0,j=result.length-1; i < arr.length; i++,j--)
{
result[j] = arr[i];
}
return result;
}
}
补充:数组还有一个apache组织开发的数组工具类ArrayUtils,可以反转、合并、打印、截取子数组等功能,但我觉得直接用ArrayList更方便。
相关链接: 需要下载common.lang.jar包