1.什么是Java的集合类?
"集合类",顾名思义,就是说用于"把一些东西集合起来的"类.当然这只是最粗浅的认识.java集合类主要负责保存盛装其他数据.因此集合类也称容器类.这个时候很容易让人联想到"数组".集合类和数组的使用有一些重叠的地方,但是集合类能实现更多更强大的的功能,使用方法也更方便快捷!
2.Java都有那些集合类
Java的集合类就像武侠小说里的昆仑派,宗门众多,弟子无量.下面有几张图可以供大家参考:
(上图来自 )
在上图中我们可以看到一些初学者会第一时间接触到的几个很有名的类:ArrayList,HashSet,TreeSet等.上图中实线边框的是实现类,折线边框的是抽象类,而点线边框的是接口.
3.简单介绍ArrayList类
可以想象ArrayList是一个进化了的数组,从前我们定义的数组要么是基本数据类型数组(包括int[],double[]等),要么是引用数据类型的数组(有String[]等).以前的数组有什么特点呢?它们只能存放 一种 数据类型:比如一个int[]数组,它里面只能放int类型的数据.而且数组里的每个对象都有自己独有的下标,总是那么泾渭分明.此外,以前的数组还有一个更加致命的天生缺陷:一个数组长度一旦被定义,就再也不能改变了!这些特性使我们的开发被严重限制!
这个时候,ArrayList为代表的集合类就来拯救我们了.我们首先以ArrayList为代表看看有哪些特点:
1.ArrayList是List的实现类
2.其数组大小可实现变化(默认大小是10,递增系数为1,这个后面解释)
3.数组内的元素可以重复
4.允许元素为null
5.存放的都是对象的引用,而非对象本身(我们可以称 集合中的对象 就是指 集合中对象的引用,因为在平时应用中没有太大影响)
6.可以允许通过下标来获取,改变,删除,插入某一元素.
看到上面的特性可以发现ArrayList类用来代替普通的数组来使用完全没有问题!
事实上,继承了Colletion类的众多子类各自有各自不同的特性.比如说HashSet类是一种 无序 的Set实现类,元素存入这个类的位置没有任何规律可循,自然也无法进行那些依靠下标来进行的操作,比如在下标为2的位置插入"123"字符串.HashSet这个类在某些情景下用处非常大.
tips:ArrayList的空间:
ArrayList类被创建时空间大小是10,也就是说可以存入10个元素.当存入第11个元素时,ArrayList内部会处理自己的空间,增加"原始空间*递增系数"个空间,即10*1=10个空间(不同的集合类有不同的原始空间大小和递增系数,可以在API中查到).
需要注意的是,上面所说的空间都是指ArrayList内部的,里面怎么处理,里面有多少空的位置对于调用者是不可知的.比如我存入3个元素后,利用size()方法查询集合大小,得到的返回值还是3,而不是10.我们更不能直接越过下标为3,4,5...的空的位置去直接去更大的下标处进行储存等操作.
而且,未被占用的空间并不是null.null本身也会占用一个元素的位置!
4.泛型
集合类有一个很突出的特点:一个集合类可以存放各种不同类型的元素.比如下面的例子:
import java.util.ArrayList;
public class Test{
<span > </span>public static void main(String[] args){
<span > </span>
<span > </span>ArrayList arr = new ArrayList();
<span > </span>arr.add(123);
<span > </span>arr.add("abc");
<span > </span>arr.add(3.1415926);
<span > </span>arr.add(true);<span > </span>
<span > </span>}
}
我新建了一个ArrayList类,然后往里面存int类型,字符串类型,浮点类型,boolean类型都没问题,编译器也不会报错.这个特性就像一把双刃剑:我们可以用这个集合类存"任何"东西,可是对此集合的后续操作将会变得非常头疼,我们会遇到这样的麻烦:取出来的这个元素到底是什么类型的呢?
Java也看到了这个问题,于是从JDK5.0开始,Java中引入了"钻石操作符"这个东西,直接看应用:
import java.util.ArrayList;
public class Test{
<span > </span>
<span > </span>public static void main(String[] args){
<span > </span><pre name="code" class="java"><span > </span>//下面这句话加入了两处<<span style="font-family: Arial, Helvetica, sans-serif;">Integer</span><span style="font-family: Arial, Helvetica, sans-serif;">>来限制arr这个集合类能存入的元素类型</span>
ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(123);
arr.add("abc");//会报错
arr.add(3.1415926);//会报错
arr.add(true);//会报错
}
}
这种处理方法称为"泛型",例如ArrayList就可以被细分成ArrayList<int>,ArrayList<String>等更多类型,方便我们使用.
5.迭代器
乍一听,迭代器是一个很高端的名字,其实并不然.
还记得当初我们是如何依次取出一个数组里的元素的吗?就像下面这样:
public class Test{
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
}
}
更高级的或者是这样:
public class Test{
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
for(int i : arr){
System.out.println(i);
}
}
}
但是当我们是用集合类来储存数组的时候,我们有了更高大上的方法:
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<String>();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("d");
arr.add("e");
Iterator<String> ite = arr.iterator();// 这样就创建了一个arr专用的迭代器
while (ite.hasNext()) {
System.out.println(ite.next());
}
}
}
事实上,在第一张图中的所有类都实现了Iterator接口,它主要包含hashNext(),next(),remove()三种方法.它还有一个子接口LinkedIterator,这个子接口又添加了三种方法,分别是add(),previous(),hasPrevious().实现更强大的遍历功能.比如返回上一个元素.