18.java 容器都有哪些?

JAVA容器类概述

1.常用容器分类

在这里插入图片描述
JAVA中的容器类主要分为两大类,一类是Map类,一类是Collection类,他们有一个共同的父接口Iterator,它提供基本的遍历,删除元素操作。Iterator还有一个子接口LinkIterator,它提供双向的遍历操作。

Collection是一个独立元素的序列,这些元素都服从一条或多条规则,它有三个子接口List,Set和Queue。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)

Map是一组成对的值键对对象,允许用键来查找值。它允许我们使用一个对象来查找某个对象,也被称为关联数组,或者叫做字典。它主要包括HashMap类和TreeMap类。Map在实际开发中使用非常广,特别是HashMap,想象一下我们要保存一个对象中某些元素的值,如果我们在创建一个对象显得有点麻烦,这个时候我们就可以用上Map了,HashMap采用是散列函数所以查询的效率是比较高的,如果我们需要一个有序的我们就可以考虑使用TreeMap。

2.Iterator类

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

接口代码如下:

public interface Iterator<E> {    
public boolean hasNext();    
public E next();    
public void remove();}

Iterator可以不用管底层数据具体是怎样存储的,都能够通过next()遍历整个容器,那么它是如何实现的呢?我们来具体分析下Java里AbstractList实现Iterator的源代码:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { 
// List接口实现了Collection<E>, Iterable<E> 
  
    protected AbstractList() {  
    }  
    
    ...  
  
    public Iterator<E> iterator() {  
    return new Itr();  // 这里返回一个迭代器
    }  
  
    private class Itr implements Iterator<E> {  // 内部类Itr实现迭代器
       
    int cursor = 0;  
    int lastRet = -1;  
    int expectedModCount = modCount;  
  
   public boolean hasNext() {  // 实现hasNext方法
           return cursor != size();  
    }  
  
    public E next() {  // 实现next方法
            checkForComodification();  
        try {  
        E next = get(cursor);  
        lastRet = cursor++;  
        return next;  
        } catch (IndexOutOfBoundsException e) {  
        checkForComodification();  
       throw new NoSuchElementException();  
        }  
    }  
  
    public void remove() {  // 实现remove方法
        if (lastRet == -1)  
        throw new IllegalStateException();  
            checkForComodification();  
  
        try {  
        AbstractList.this.remove(lastRet);  
        if (lastRet < cursor)  
            cursor--;  
        lastRet = -1;  
        expectedModCount = modCount;  
       } catch (IndexOutOfBoundsException e) {  
       throw new ConcurrentModificationException();  
        }  
    }  
  
    final void checkForComodification() {  
        if (modCount != expectedModCount)  
        throw new ConcurrentModificationException();  
    }  
    }  
}

可以看到,实现next()是通过get(cursor),然后cursor++,通过这样实现遍历。

这部分代码不难看懂,唯一难懂的是remove操作里涉及到的expectedModCount = modCount;

在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程中集合的安全性。

从源代码里可以看到增删操作都会使modCount++,通过和expectedModCount的对比,迭代器可以快速的知道迭代过程中是否存在list.add()类似的操作,存在的话快速失败!

参考文章1
参考文章2
参考文章3
参考文章4
参考文章5
参考文章6
参考文章7

参考文章8

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值