欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

18.java 容器都有哪些?

程序员文章站 2024-03-05 13:03:36
...

JAVA容器类概述

1.常用容器分类

18.java 容器都有哪些?
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

相关标签: java 数据结构