Java容器类

1、首先来看写容器类关系图,帮助记忆

容器类关系图

  • 虚线框表示抽象类;
  • 实线框表示实体类;
  • 点线带箭头表示实现了那个接口;
  • 实线带箭头表示继承了那个类;
  • 实体框代表常用的实体类

2、容器类持有对象方式

Collection : 是最基本的集合接口。只允许每个位置上放一个对象。它包括“以一定顺序持有一组对象”的List,以及“只能允许添加不重复对象”的Set。你可以用add()方法向Collection对象中加元素。
Map : 请注意,Map没有继承Collection接口。Map提供key到value的映射,以(key,value)键值对的形式存在。一个Map中不能包含相同的key,每个key只能映射一个value。你可以用put()方法往Map里面加元素。

Collection 和 Collections的区别:

Collections(以及Arrays)是个java.util下的一个工具类,它包含有各种有关集合(或数组)操作的静态方法,实现对各种集合(或数组)的搜索、排序、线程安全化等操作。
Collection是个java.util下的接口,它是各种集合结构的父接口。继承自它的接口主要有Set 和List。

3、Iterable接口
Iterable是1.5引入的新特性,Iterator是1.2就有了,二者都是为了迭代造作,Iterable只是包装了Iterator,从而允许实现此接口的对象成为foreach语句的目标,而且这样的话,更方便以后的扩展。

比如List一族或者Set一族,都是实现了Iterable接口,但并不直接实现Iterator接口。

package java.util;
public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}
package java.lang;
import java.util.Iterator;
/**
 * Implementing this interface allows an object to be the target of
 * the "foreach" statement.
 * @since 1.5
 */
public interface Iterable<T> {
    Iterator<T> iterator();
}

4、Set接口
Set集合不允许包含相同的元素。如果试图将两个相同的元素加入同一个Set集合中,则添加操作失败,add方法返回false;
Set判断两个对象是否相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

HashSet类: 是Set接口的一个子类,主要的特点是:里面不能存放重复元素,而且采用散列的存储方法,所以没有顺序。这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致。

HashSet有以下特点:

  • 不能保证元素的排序顺序,顺序有可能发生变化。因为采用的是散列的存储方法;
  • 不是同步的,如果有多个线程同时修改了HashSet集合时,必须通过代码来保证其同步;
  • 集合元素可以是null,但只能放入一个null。

注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法时,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。

这是因为两个对象通过equals()方法返回true,通过hashCode()方法返回不同的hashCode值时,这将导致HashSet会将两个这两个对象保存在HashSet的不同位置,从而两个对象都添加成功,这是不符合Set集合规则的。

如果两个对象通过equals()方法返回false,而通过hashCode()方法返回相同的hashCode值,HashSet试图将这两个对象保存在同一个位置,但实际上又不行(否则只剩下一个对象),所以也不行。

TreeSet类: TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的对象,其类型应该相同,且实现了Comparable接口。

自然排序:
Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类的对象就可以比较大小。

因为向TreeSet中添加元素时,TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系。如果对应的类没有实现Comparable接口;或者不是同一个类的对象(或者不存在继承关系),则无法转化为相同的类型,调用compareTo(Object obj)方法来比较大小。这都将会引发ClassCastException异常。

当把一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo(Object obj)方法与容器中的其他对象比较大小,然后根据红黑树算法决定它的存储位置。如果两个对象通过compareTo(Object obj)比较相等,TreeSet即认为它们存储同一位置。

注意,当需要把一个对象放入TreeSet中时,重写该对象对应类的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致结果,其规则是:如果两个对象通过equals方法比较返回true时,这两个对象通过compareTo(Object obj)方法比较应返回0.

如果两个对象通过equals方法比较返回true,但这两个对象通过compareTo(Object obj)方法比较不返回0时,这将导致TreeSet将会把这两个对象保存在不同位置,从而两个对象都可以添加成功,这与Set集合的规则有点出入。

如果两个对象通过compareTo(Object obj)方法比较返回0时,但它们通过equals方法比较返回false时将更麻烦:因为两个对象通过compareTo(Object obj)方法比较相等,TreeSet将试图把它们保存在同一个位置,但实际上又不行(否则将只剩下一个对象),所以处理起来比较麻烦。

定制排序:
TreeSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列。如果需要实现定制排序,例如降序,则可以使用Comparator接口。该接口里包含一个int compare(T o1, T o2)方法,该方法用于比较o1和o2的大小。

import java.util.Comparator;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
    //传入实现了comparator接口的内部类,重写compare(T o1,T o2)方法
        TreeSet<Integer> set = new TreeSet<Integer>(
                new Comparator<Integer>(){
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        int m1 = (int)o1;
                        int m2 = (int)o2;
                        if(m1>m2){
                            return -1;
                        }else if(m1<m2){
                            return 1;
                        }else{
                            return 0;
                        }                       
                    }                   
                }
            );
        set.add(9);set.add(-1);set.add(10);
        set.add(-3);set.add(19);set.add(0);
        for(Integer num:set){
            System.out.print(num+" ");
        }
    }
}

//输出结果为:19 10 9 0 -1 -3 

当使用定制排序时,加入到TreeSet中的对象可以不实现Comparator接口,但是在创建TreeSet对象时,传入了一个实现了Comparator接口匿名内部类,重写compare(T o1,T o2)方法。

LinkedHashSet类: LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

4、List接口
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。List允许有相同的元素

ArrayList类: List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。

每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

ArrayList也是非同步的(unsynchronized)。

LinkedList类: List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

注意:LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。

Vector类: Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除某些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

Stack 类: Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

ArrayList和Vector的区别

  1. 同步性: Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常;
  2. 数据增长: 当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半。

5、Map接口: 请注意,Map没有继承Collection接口,Map将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Hashtable类:
添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

注意,由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode()和equals()方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,按照散列函数的定义,如果两个对象相同,即通过equals()返回true,则它们的hashCode必须相同。(HashSet类似)。牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。

HashMap类: HashMap和Hashtable类似,不同之处在于HashMap是非同步的;Hashtable不允许使用null作为key 和 Value,如果试图把null值放入Hashtable,将会引发NullPointerException异常;但是HashMap可以使用null作为key 和 value。由于HashMap里的key不能重复,所以Key-value对,最多只能有一项key为null,但可以有无数个value为空。

WeakHashMap类: WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值