集合框架

本文详细介绍了集合框架的基本概念,包括集合的定义、集合框架的组成部分及其优势。深入探讨了Collection、List、Set、Map等核心接口及其实现类的特点与用法,并解析了Comparable与Comparator接口的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


什么是集合?

很难给集合下一个精确的定义,通常情况下,把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合。比如,用Java编程的所有程序员,全体中国人等。通常集合有两种表示法,一种是列举法,比如集合A={1,2,3,4},另一种是性质描述法,比如集合B={X|0<X<100且X属于整数}。集合论的奠基人康托尔在创建集合理论给出了许多公理和性质,这都成为后来集合在其它领域应用的基础。

什么事集合框架?

那么有了集合的概念,什么是集合框架呢?集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
接口:即表示集合的抽象数据类型。接口提供了让我们对集合中所表示的内容进行单独操作的可能。
实现:也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。
算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法,例如查找、排序等。这些算法通常是多态的,因为相同的方法可以在同一个接口被多个类实现时有不同的表现。事实上,算法是可复用的函数。

集合框架简略图:


为什么要有集合框架?

1,减少设计辛劳
集合框架通过提供有用的数据结构和算法使你能集中注意力于你的程序的重要部分上,而不是为了让程序能正常运转而将注意力于低层设计上。通过这些在无关API之间的简易的互用性,使你免除了为改编对象或转换代码以便联合这些API而去写大量的代码。

2,提高速度质量
集合框架通过提供对有用的数据结构和算法的高性能和高质量的实现使你的程序速度和质量得到提高。因为每个接口的实现是可互换的,所以你的程序可以很容易的通过改变一个实现而进行调整。另外,你将可以从写你自己的数据结构的苦差事中解脱出来,从而有更多时间关注于程序其它部分的质量和性能。

集合接口

Collection 接口
用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。

他们共同的方法:

(1) 单元素添加、删除操作:
        boolean add(Object o):将对象添加给集合
        boolean remove(Object o): 如果集合中有与o相匹配的对象,则删除对象o,否则返回false
(2) 查询操作:
        int size() :返回当前集合中元素的数量
        boolean isEmpty() :判断集合中是否有任何元素
        boolean contains(Object o) :查找集合中是否含有对象o
        Iterator iterator() :返回一个迭代器,用来访问集合中的各个元素
(3) 组操作 :作用于元素组或整个集合
        boolean containsAll(Collection c): 查找集合中是否含有集合c 中所有元素
        boolean addAll(Collection c) : 将集合c 中所有元素添加给该集合
        void clear(): 删除集合中所有元素
        void removeAll(Collection c) : 从集合中删除集合c 中的所有元素
        void retainAll(Collection c) : 从集合中删除集合c 中不包含的元素
(4) Collection转换为Object数组 :
        Object[] toArray() :返回一个内含集合所有元素的array
        Object[] toArray(Object[] a) :返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。
此外,您还可以把集合转换成其它任何其它的对象数组。但是,您不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。”
Collection不提供get()方法。如果要遍历Collectin中的元素,就必须用Iterator。

那么什么是iterator呢?

Collection 接口的iterator()方法返回一个 Iterator。Iterator接口方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection 中除去适当的元素。
(1) boolean hasNext(): 判断是否存在另一个可访问的元素
     Object next(): 返回要访问的下一个元素。如果到达集合结尾,则抛出NoSuchElementException异常。
(2) void remove(): 删除上次访问返回的对象。本方法必须紧跟在一个元素的访问后执行。如果上次访问后集合已被修改,方法将抛出IllegalStateException。
eg:

Iterator it = t.iterator();
		while(it.hasNext()){
			Student s = (Student)it.next();
			System.out.println(s.getName()+" "+s.getAge());
		}

谈到iterator不得不提增强for循环

增强for循环可以简化代码,而又可以代替iterator的功能。

eg:

class CollectionDemo{
	public static void main(String[] args){
		ArrayList<String> al = new ArrayList<String>();
		al.add("ave");
		al.add("bdc");
		al.add("aad");
		for(String s : al){//增强for循环
			System.out.println(s);
		}
		String[] arr = al.toArray(new String[al.size()]);
		System.out.println(Arrays.toString(arr));
	}
}


collection其下子接口:

1,List接口

List 接口继承了 Collection 接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。

 LinkedList类
LinkedList类添加了一些处理列表两端元素的方法。
(1) void addFirst(Object o): 将对象o添加到列表的开头
        void addLast(Object o):将对象o添加到列表的结尾
(2) Object getFirst(): 返回列表开头的元素
        Object getLast(): 返回列表结尾的元素
(3) Object removeFirst(): 删除并且返回列表开头的元素
        Object removeLast():删除并且返回列表结尾的元素
(4) LinkedList(): 构建一个空的链接列表
        LinkedList(Collection c): 构建一个链接列表,并且添加集合c的所有元素
使用这些新方法,您就可以轻松的把 LinkedList 当作一个堆栈、队列或其它面向端点的数据结构。”

2,ArrayList类
ArrayList类封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个capacity。这个capacity表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的capacity在常量时间内自动增加。,在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
(1) void ensureCapacity(int minCapacity): 将ArrayList对象容量增加minCapacity
(2) void trimToSize(): 整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。

由于ArrayList的效率比较高,所以这个集合类是最常用的。


2,Set接口

Set 接口继承 Collection 接口,而且它不允许集合中存在重复项,每个具体的 Set 实现类依赖添加的对象的 equals()方法来检查独一性。Set接口没有引入新方法,所以Set就是一个Collection,只不过其行为不同。

HashSet类
(1) HashSet(): 构建一个空的哈希集
(2) HashSet(Collection c): 构建一个哈希集,并且添加集合c中所有元素
(3) HashSet(int initialCapacity): 构建一个拥有特定容量的空哈希集
(4) HashSet(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空哈希集。LoadFactor是0.0至1.0之间的一个数

3.5.2. TreeSet类
(1) TreeSet():构建一个空的树集
(2) TreeSet(Collection c): 构建一个树集,并且添加集合c中所有元素
(3) TreeSet(Comparator c): 构建一个树集,并且使用特定的比较器对其元素进行排序
“comparator比较器没有任何数据,它只是比较方法的存放器。这种对象有时称为函数对象。函数对象通常在“运行过程中”被定义为匿名内部类的一个实例。”
TreeSet(SortedSet s): 构建一个树集,添加有序集合s中所有元素,并且使用与有序集合s相同的比较器排序

Map接口

Map接口不是Collection接口的继承。Map接口用于维护键/值对(key/value pairs)。该接口描述了从不重复的键到值的映射。

(1) 添加、删除操作:
        Object put(Object key, Object value): 将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回null
        Object remove(Object key): 从映像中删除与key相关的映射
        void putAll(Map t): 将来自特定映像的所有元素添加给该映像
        void clear(): 从映像中删除所有映射
“键和值都可以为null。但是,您不能把Map作为一个键或值添加给自身。”
(2) 查询操作:
        Object get(Object key): 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找到该关键字,则返回null
        boolean containsKey(Object key): 判断映像中是否存在关键字key
        boolean containsValue(Object value): 判断映像中是否存在值value
        int size(): 返回当前映像中映射的数量
        boolean isEmpty() :判断映像中是否有任何映射
(3) 视图操作 :处理映像中键/值对组
        Set keySet(): 返回映像中所有关键字的视图集
“因为映射中键的集合必须是唯一的,您用Set支持。你还可以从视图中删除元素,同时,关键字和它相关的值将从源映像中被删除,但是你不能添加任何元素。”
        Collection values():返回映像中所有值的视图集
“因为映射中值的集合不是唯一的,您用Collection支持。你还可以从视图中删除元素,同时,值和它的关键字将从源映像中被删除,但是你不能添加任何元素。”
        Set entrySet(): 返回Map.Entry对象的视图集,即映像中的关键字/值对
“因为映射是唯一的,您用Set支持。你还可以从视图中删除元素,同时,这些元素将从源映像中被删除,但是你不能添加任何元素。”

map集合中的两个常用类:treemap  hashmap

集合框架”提供两种常规的 Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。这个TreeMap没有调优选项,因为该树总处于平衡状态。

HashMap类
为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
(1) HashMap(): 构建一个空的哈希映像
(2) HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
(3) HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
(4) HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像

4.4.2. TreeMap类
TreeMap没有调优选项,因为该树总处于平衡状态。
(1) TreeMap():构建一个空的映像树
(2) TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
(3) TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
(4) TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序


Comparable接口和Comparator接口
在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现 Comparable接口以提供一定排序方式,但这样只能实现该接口一次。对于那些没有实现Comparable接口的类、或者自定义的类,您可以通过 Comparator接口来定义您自己的比较方式。

Comparable接口
在java.lang包中,Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许您把集合排序成自然顺序。
(1) int compareTo(Object o): 比较当前实例对象与对象o,如果位于对象o之前,返回负值,如果两个对象在排序中位置相同,则返回0,如果位于对象o后面,则返回正值
在 Java 2 SDK版本1.4中有二十四个类实现Comparable接口。下表展示了8种基本类型的自然排序。虽然一些类共享同一种自然排序,但只有相互可比的类才能排序。利用Comparable接口创建您自己的类的排序顺序,只是实现compareTo()方法的问题。通常就是依赖几个数据成员的自然排序。同时类也应该覆盖equals()和hashCode()以确保两个相等的对象返回同一个哈希码。

eg:

class Student implements Comparable{//强制让学生类有比较性
	private String name;
	private int age;
	Student(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		System.out.println(this.name+" "+s.name);
		if(this.age>s.age)
			return 1;
		if(this.age == s.age){
			return this.name.compareTo(s.name);
		}
		return -1;
		
	}
}

Comparator接口

若一个类不能用于实现java.lang.Comparable,或者您不喜欢缺省的Comparable行为并想提供自己的排序顺序(可能多种排序方式),你可以实现Comparator接口,从而定义一个比较器。
(1)int compare(Object o1, Object o2): 对两个对象o1和o2进行比较,如果o1位于o2的前面,则返回负值,如果在排序顺序中认为o1和o2是相同的,返回0,如果o1位于o2的后面,则返回正值
“与Comparable相似,0返回值不表示元素相等。一个0返回值只是表示两个对象排在同一位置。由Comparator用户决定如何处理。如果两个不相等的元素比较的结果为零,您首先应该确信那就是您要的结果,然后记录行为。”
(2)boolean equals(Object obj): 指示对象obj是否和比较器相等。该方法覆写Object的equals()方法,检查的是Comparator实现的等同性,不是处于比较状态下的对象。” 

eg:改变学生单纯的按姓名比较为按姓名和年龄共同比较:

class MyComparator implements Comparator{
	public int compare(Object o1,Object o2){
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num == 0){
			return new Integer(s1.getAge()).compareTo(s2.getAge()); 
		}
		return num;
	}
}
使用自定义的比叫器:

TreeSet t = new TreeSet(new MyComparator());


泛型

在实际开发中我们发现在使用类型时可能会出现使用的类型不正确但是能通过编译,而运行时就发生错误,这是程序员不希望看到的。泛型解决了安全问题,避免了强制类型转换

eg:

class Student{}
class Worker{}
class Utils<T>{
	private T t;
	public void setObject(T t){
		this.t = t;
	}
	public T getObject(){
		return t;
	}
}
class CollectionDemo{
	public static void main(String[] age){
		Utils<Student> u = new Utils<Student>();
		u.setObject(new Student());
		Worker s = u.getObject();

	}
}
可以看到应为定义了泛型student 所以确定了u是student类型的对象这就避免了程序员弄不清谁是谁的问题了,但然强将u返回给worker类型就会编译报错如下:


泛型还可以这样使用:

class Demo<T>{
	public void show(T t){
		System.out.println("show"+t);
	}
	public void print(T t){
		System.out.println("print"+t);
	}
}
class Demo1{
	public <T> void show(T t){
		System.out.println("show"+t);
	}
	public <T> void print(T t){
		System.out.println("print"+t);
	}
}
class Demo2<T>{
	public void show(T t){
		System.out.println("show"+t);
	}
	public <S> void print(S s){
		System.out.println("print"+s);
	}
	public static <W> void method(W w){
		System.out.println("method"+w);
	} //静态方法不能访问类上定义的泛型
}
在创建一个集合对象是经常会加上一个类型限定如:

TreeMap<Student> tm = new TreeMap<Student>();
ArrayList<Student> al = new ArrayList<Student>():
.......





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值