1、类集设置的目的。
- 普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构, 所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现。 类集中最大的几个操作接口:
Collection、Map、Iterator
,这三个接口为以后要使用的最重点的接口。 所有的类集操作的接口或类都在java.util
包中。
2、Collection 接口(重点)
Collection
接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。 此接口定义在java.util
包中。- 此接口使用了泛型技术,在 JDK 1.5 之后为了使类集操作的更加安全,所以引入了泛型。此接口的定义如下:
public interface Collection<E> extends Iterable<E>
- 常用方法:
在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set
。
3、List 接口(重点)
- 在整个集合中
List
是Collection
的子接口,里面的所有内容都是允许重复的。List
子接口的定义:
public interface List<E> extends Collection<E>
- 此接口上依然使用了泛型技术。此接口对于 Collection 接口来讲有如下的扩充方法:
- 在
List
接口中有以上 10 个方法是对已有的Collection
接口进行的扩充。 所以,List
接口拥有比Collection
接口更多的操作方法。 了解了List
接口之后,那么该如何使用该接口呢?需要找到此接口的实现类,常用的实现类有如下几个:ArrayList
(95%)、Vector
(4%)、LinkedList
(1%)。
3.1、ArrayList(重点)
ArrayList
是List
接口的子类,此类的定义如下:
public class ArrayList<E> extends AbstractList<E>
此类继承了AbstractList
类。AbstractList
是List
接口的子类。AbstractList
是个抽象类,适配器设计模式。- 范例:增加及取得元素
package org.listdemo.arraylistdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo01 {
public static void main(String[] args) {
List<String> all = new ArrayList<String>(); // 实例化List对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从Collection接口继承而来
all.add(0, "LAMP "); // 增加内容,此方法是List接口单独定义的
all.add("world"); // 增加内容,此方法从Collection接口继承而来
all.remove(1); // 根据索引删除内容,此方法是List接口单独定义的
all.remove("world");// 删除指定的对象
for (int x = 0; x < all.size(); x++) { // size()方法从Collection接口继承而来
System.out.print(all.get(x) + "、"); // 此方法是List接口单独定义的
}
}
}
3.2、Vector 类和 ArrayList 类的区别(重点)
- 相同点。这两个类都实现了
List
接口(List
接口继承了Collection
接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的数据是允许重复的,这是HashSet
之类的集合的最大不同处,HashSet
之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素。 - 不同点。
ArrayList
与Vector
的区别,这主要包括两个方面:
(1)同步性:
Vector
是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList
是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList
,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector
,因为不需要我们自己再去考虑和编写线程安全的代码。
备注:对于Vector&ArrayList、Hashtable&HashMap,
要记住线程安全的问题,记住Vector
与Hashtable
是旧的,是 java 一诞生就提供了的,它们是线程安全的,ArrayList
与HashMap
是 java2时才提供的,它们是线程不安全的。
(2)数据增长:
ArrayList
与Vector
都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList
与Vector
的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector 默认增长为原来两倍,而ArrayList
的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的 1.5 倍)。ArrayList
与Vector
都可以设置初始的空间大小,Vector
还可以设置增长的空间大小,ArrayList
没有提供设置增长空间的方法。总结:即Vector
增长原来的1倍,ArrayList
增加原来的 0.5 倍。
4、Set 接口(重点)
Set
接口也是Collection
的子接口,与List
接口最大的不同在于,Set
接口里面的内容是不允许重复的。Set
接口并没有对Collection
接口进行扩充,基本上还是与Collection
接口保持一致。因为此接口没有List
接口中定义 的get(int index)
方法,所以无法使用循环进行输出。- 在此接口中有两个常用的子类:
HashSet、TreeSet
4.1、散列存放:HashSet(重点)
Set
接口使用的方法全部都是Collection
接口定义而来的。Java SE 核心技术HashSet
属于散列的存放类集,里面的内容是无序存放的。- 例
package org.listdemo.hashsetdemo;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo01 {
public static void main(String[] args) {
Set<String> all = new HashSet<String>(); // 实例化Set接口对象
all.add("A");
all.add("B");
Object obj[] = all.toArray(); // 将集合变为对象数组
for (int x = 0; x < obj.length; x++) {
System.out.print(obj[x] + "、");
}
}
}
4.2、排序的子类:TreeSet(重点)
- 在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。
4.3、小结
- 关于
TreeSet
的排序实现,如果是集合中对象是自定义的或者说其他系统定义的类没有实现Comparable
接口,则不能实现TreeSet
的排序,会报类型转换(转向 Comparable 接口)错误。 换句话说要添加到TreeSet
集合中的对象的类型必须实现了Comparable
接口。 不过TreeSet
的集合因为借用了Comparable
接口,同时可以去除重复值,而HashSet
虽然是Set
接口子类,但是对于没有复写Object
的equals 和 hashCode
方法的对象,加入了HashSet
集合中也是不能去掉重复值的。
5、Map 接口(重点)
Map
接口。里面的所有内容都按照key-value
的形式保存,也称为二元偶对象。- 此接口定义如下:
public interface Map<K,V>
- 此接口与
Collection
接口没有任何的关系,是第二大的集合操作接口。此接口常用方法如下:
Map
本身是一个接口,所以一般会使用以下的几个子类:HashMap、TreeMap、Hashtable
5.1、HashMap 与 Hashtable 的区别(重点)
- 相同点。均实现了Map接口
- 不同点。
6、List 和 Map 区别?
List
存储单列数据的集合,Map
是存储键和值这样的双列数据的集合;List
中存储的数据是有顺序,并且允许重复;Map
中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。
7 、List, Set, Map 是否继承自 Collection 接口?
List,Set 是,Map
不是。Map
接口与Collection
接口没有任何的关系,是第二大的集合操作接口。
8 、说出 ArrayList,Vector, LinkedList 的存储性能和特性。
ArrayList
和Vector
都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector
由于使用了synchronized
方法(线程安全),通常性能上较ArrayList
差,而LinkedList
使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。LinkedList
也是线程不安全的,LinkedList
提供了一些方法,使得LinkedList
可以被当作堆栈和队列来使用。
9 、Collection 和 Collections 的区别。
Collection
是集合类的上级接口,继承于他的接口主要有Set
和List
.Collections
是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
10 、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用== 还是 equals()? 它们有何区别?
Set
里的元素是不能重复的,元素重复与否是使用equals()
方法进行判断的。equals()
和==
方法决定引用值是否指向同一对象equals()
在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
11、集合类都有哪些?主要方法?
- 最常用的集合类是
List
和Map
。 List
的具体实现包括ArrayList 和 Vector,
它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。List
适用于按数值索引访问元素的情形。Map
提供了一个更通用的元素存储方法。Map
集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。- 对于
set
,大概的方法是add,remove, contains
; - 对于
map
,大概的方法就是put,remove,contains
等 List
类有get(int index)
这样的方法,因为它可以按顺序取元素,而set
类中没有 。List
和set
都可以迭代出所有元素,迭代时先要得到一个iterator
对象,所以,set
和list
类都有一个iterator
方法,用于返回那个iterator
对象。map
可以返回三个集合,一个是返回所有的key
的集合,另外一个返回的是所有value
的集合,再一个返回的key
和value
组合成的EntrySet
对象的集合,map
也有get
方法,参数是key
,返回值是key
对应的value
。