Java集合总结(一)

Java容器入门

Java语言提供了大量的集合框架,用户可以直接使用,这里对常用的集合接口以及实现做一简单总结。

整体框架

Java容器总结

接口介绍

Iterable接口

迭代器接口,提供用于遍历、选择容器元素的迭代器,由方法iterator()返回一个Iterator类型的对象,该对象提供了遍历的各种方法:

1.hasNext()

判断是否还存在下一个元素,如果存在返回true。

2.next()

获得下一个元素对象。

3.remove()

从集合中删除一个元素,对于需要在循环过程删除元素的,一定要用迭代器进行删除

Collection接口

Collection是一个集合的抽象,提供了集合的各种方法:

查询操作

1.size(),isEmpty()

用于获取集合的元素个数,以及判断集合是否为空。不同实现类中size的实现细节不同,尤其是并发的集合实现,size可能需要遍历整个集合,使用的时候一定要注意对性能的影响。

用于判断集合是否为空,最好使用isEmpty(),尽量不要用size() != 0。

2.contains(),containsAll()

用于判断传入的元素、集合是否属于本集合。集合的元素要注意equals方法的编写,内部一般会使用equals方法判断元素是否相等。对于containsAll,只要有一个元素不存在,即返回false。

3.toArray(),toArray(T[])

将集合中的元素,返回到一个数组中,返回的数组引用不能指向集合中的任何实现对象,因此在方法中需要创建一个新的数组返回。这个方法为集合类型和数组类型的API接口提供了一个”桥梁”。

而toArray(T[])是个模板函数,在运行时可以转换为相应类型的数组,在toArray()的基础上,增加了类型转换的能力。

修改操作

1.add(),addAll()

向集合添加元素或者添加传入集合中的所有元素,对于拒绝添加元素的场景,需要返回UnsupportedOperationException,ClassCastException,NullPointerException等runntime异常信息,而添加元素失败会false,调用程序需要判断返回值。

对于addAll()方法,不同的实现类中,返回的逻辑不同,需要针对不同的场景特别对待。

2.remove(),removeAll()

从集合中删除元素,或者删除传入集合中的所有元素,对于拒绝删除元素的场景,需要返回相应的runntime异常信息。如果删除后容器没有变化,需要返回false,调用程序需要根据使用场景判断返回值。

3.retainAll()

取两个集合的交集,如果传入的集合为空,那么最后结果为空。

4.clear()

清除集合中的所有元素

比较和哈希操作

1.hash(),equals()

hash是所以元素的哈希之和。
equals是所有元素相等,对于Map类型,和顺序无关,对于List类型,和顺序有关,根据不同实现会有不同的逻辑,需要根据使用场景处理。

实现介绍

容器的具体实现,根据元素的属性和元素直接的关系,我这里分为三大类:集合、列表、映射。

集合:元素的简单集合,不允许有重复的元素存在,可以无序或者有序

列表:元素的顺序集合,允许有重复的元素存在

映射:每个元素是一个键值对关系,键不允许重复,值允许重复,可以无序或者有序

以上是归纳出的三种基本的容器类型,根据使用的场景,还可以再细分为队列、双端队列、堆栈等。

集合

集合基础接口是set,用于描述一组不重复的元素的集合,对应于数学上的集合抽象,常用于存放某些元素,并且需要判断元素是否已存在在集合中的场景。集合接口提供了基本的集合操作add,remove,contains,size等方法。

常用的不支持并发的实现类有HashSet、TreeSet、LinkedHashSet。这几种集合内部都是基于Map的数据结构存储,将元素存储在键里,值存放一个无用的对象。

  1. HashSet
    HashSet基于HashMap实现,因此遍历时无法保证顺序,并且顺序有可能会改变;只允许存在一个null元素。

  2. TreeSet
    TreeSet基于TreeMap实现,实现了SortedSet接口,提供了一些基于顺序的集合查询操作。这个集合的元素需要实现Comparable接口,在插入的时候排序插入,遍历的时候也是基于元素的顺序遍历;元素不允许为null。

  3. LinkedHashSet
    LinkedHashSet基于LinkedHashMap实现,遍历时元素顺序可以保证和插入顺序相同;只允许存在一个null元素。

    示例代码如下:

    以下是一个测试的元素类型,修改了常规的hashcode算法,改为取2的余数,因此不同的元素可能会引起哈希冲突。

public class HashRemainderOfTwo implements Comparable<Object>
{
    private final int i;

    public HashRemainderOfTwo(int i)
    {
        this.i = i;
    }


    @Override
    public String toString() {
        return "" + i + "";
    }


    /**
     * 一个特殊的hashCode,取2的余数,因此不同对象在hash的时候会引起hash冲突
     */
    @Override
    public int hashCode() {
        return i%2;
    }


    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        HashRemainderOfTwo other = (HashRemainderOfTwo) obj;
        if (i != other.i)
            return false;
        return true;
    }

    @Override
    public int compareTo(Object o) {
        HashRemainderOfTwo oo = (HashRemainderOfTwo)o;
        return this.i - oo.i;
    }

}

对三种Set实现类,按照不同的顺序插入元素,再遍历元素,看输出结果。插入顺序为1,4,2,null。所有的元素hash结果都是0。

public class SetTest 
{

    static final int hash(Object key) 
    {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    public static void main(String[] args)
    {
        HashRemainderOfTwo t1 = new HashRemainderOfTwo(1);
        HashRemainderOfTwo t2 = new HashRemainderOfTwo(2);
        HashRemainderOfTwo t4 = new HashRemainderOfTwo(4);

        Set<HashRemainderOfTwo> set = new HashSet<HashRemainderOfTwo>();
        set.add(t1);
        set.add(t4);
        set.add(t2);
        set.add(null);
        set.add(null);//只可能有一个null,重复插入无效

        System.out.println(set);

        Set<HashRemainderOfTwo> tree = new TreeSet<HashRemainderOfTwo>();
        tree.add(t1);
        tree.add(t4);
        tree.add(t2);
//      tree.add(null);//TreeSet的元素不允许为null

        System.out.println(tree);

        Set<HashRemainderOfTwo> linkset = new LinkedHashSet<HashRemainderOfTwo>();
        linkset.add(t1);
        linkset.add(t4);
        linkset.add(t2);
        linkset.add(null);
        linkset.add(null);//只可能有一个null,重复插入无效

        System.out.println(linkset);
    }

}

输出结果:

HashSet:[4, 2, null, 1]
TreeSet:[1, 2, 4]
LinkedHashSet:[1, 4, 2, null]

可以看出,HashSet是顺序无关的,而TreeSet以元素大小排序,LinkedHashSet以插入顺序排序。

而对应于上面集中集合,支持并发的集合实现有:

—未完待续,下篇分析列表类型的容器实现—

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值