Java核心技术笔记——数据结构(1)
2016-01-20 15:16
561 查看
java设计了一套集合(也叫容器)类库,来支持最常用的数据结构,Java集合类库采用接口与实现分离的原则。下面主要梳理集合接口,集合类(包括集合抽象类和具体实现类)。
集合有两个基本接口Collection和Map
(1) Collection接口的源码如下:
(2)Map用来存放键值对,Map接口源码如下:
注意,在Java中访问集合中某个位置元素,要使用迭代器(Iterator)。
(3)Iterator接口的源码如下:
List是一个顺序排列集合接口,List在特定位置添加元素的方法有两种,一种是整数索引,一种是列表迭代器。
(4)List接口的源码如下:
由于Collection有的子集合(如Set)是无序的,所以Iterator接口中无add方法,但是对于List子集合需要使用迭代器添加指定位置的元素,因此ListIterator继承Iterator,提供了add方法。
(5)ListIterator接口源码如下:
Set接口和Collection接口的方法一样,这里Java为什么要定义一个新的接口?是为了从概念上区分集合与集,方面扩展。
SortedSet和SortedMap接口,顾名思义给开发者暴露了排序的方法,并可以返回某个范围内的子集
(6)SortedSet的源码如下:
(7)SortedMap的源码如下:
Java SE6引入了NavigableSet和NavigableMap接口,用来在有序集和Map中查找遍历方法
(8)NavigableSet源码如下:
(9)NavigableMap源码如下:
队列是在尾部添加一个元素,在头部删除一个元素。双端队列是在头部和尾部都可以删除元素
(10)Queue的源码如下:
(11)Deque(双端队列接口)源码如下:
RandomAccess接口用于监测List随机访问的效率,该接口没有方法,ArrayList继承了该接口。
(12)RandomAccess源码:
下面是Java集合类图:
AbstractList、AbstractSet、AbstractQueue、AbstractSequentialList
这里以AbstractCollection源码为例分析一下:
AbstractCollection的源码如下:
下面是Java集合具体类的主要特征,如下表:
1 Java集合接口
Java的集合接口关系图如下:集合有两个基本接口Collection和Map
(1) Collection接口的源码如下:
public interface Collection<E> extends Iterable<E> { // Query Operations int size(); boolean isEmpty(); boolean contains(Object o); //返回迭代器对象,用来访问集合中的元素 Iterator<E> iterator(); //返回集合的对象数组 Object[] toArray(); //添加元素 boolean add(E e); //移除元素 boolean remove(Object o); //判断传入集合是否被包含 boolean containsAll(Collection<?> c); //与传入集合求交集 boolean retainAll(Collection<?> c); boolean addAll(Collection<? extends E> c); }
(2)Map用来存放键值对,Map接口源码如下:
public interface Map<K,V> { // Query Operations int size(); boolean isEmpty(); boolean containsKey(Object key); boolean containsValue(Object value); //获取对应k的值,如果没有这个值,则返回null,K可以为null V get(Object key); // Modification Operations //插入k和v,此处可以插入k为null的键值对,但是v不能为null V put(K key, V value); V remove(Object key); // Bulk Operations void putAll(Map<? extends K, ? extends V> m); void clear(); // Views /*--注意从下面三个返回的集中,可以删除元素,与此同时也删除了Map中的元素,但是不能添加元素---***/ //返回Map中所有K的Set集 Set<K> keySet(); //返回Map中所有V的Collection集合 Collection<V> values(); //整个键值对作为一个Set集返回 Set<Map.Entry<K, V>> entrySet(); interface Entry<K,V> { K getKey(); V getValue(); V setValue(V value); boolean equals(Object o); int hashCode(); } // Comparison and hashing boolean equals(Object o); int hashCode(); }
注意,在Java中访问集合中某个位置元素,要使用迭代器(Iterator)。
(3)Iterator接口的源码如下:
public interface Iterator<E> { //返回将要访问的下一个对象,如果已经是集合的最后一个元素,将抛出NoSuchElementException错误 E next(); //由于上面方法抛出错误,因此在访问集合元素之前,先判断是否有下一个元素 boolean hasNext(); //移除元素之前,要先使用next方法定位到改元素; void remove(); }
List是一个顺序排列集合接口,List在特定位置添加元素的方法有两种,一种是整数索引,一种是列表迭代器。
(4)List接口的源码如下:
public interface List<E> extends Collection<E> { // Query Operations //继承Collection方法,参考Collection源码分析 int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); ........ // Positional Access Operations //获取给定位置的元素 E get(int index); //用新元素取代给定位置元素,返回原来的元素 E set(int index, E element); //通过整数索引,在给定位置添加元素 void add(int index, E element); //移除给定位置的元素 E remove(int index); // Search Operations //返回与给定元素相等的元素在列表中第一次出现的位置,如果没有返回-1 int indexOf(Object o); //返回与给定元素相等的元素在列表中最后一次出现的位置,如果没有放回-1 int lastIndexOf(Object o); // List Iterators //返回一个列表迭代器 ListIterator<E> listIterator(); //返回一个列表迭代器,第一次调用next后,返回的给定索引的元素 ListIterator<E> listIterator(int index); // View //返回List的某个范围内的子集合 List<E> subList(int fromIndex, int toIndex); }
由于Collection有的子集合(如Set)是无序的,所以Iterator接口中无add方法,但是对于List子集合需要使用迭代器添加指定位置的元素,因此ListIterator继承Iterator,提供了add方法。
(5)ListIterator接口源码如下:
public interface ListIterator<E> extends Iterator<E> { // Query Operations //继承Iterator方法,参考Iterator源码分析 boolean hasNext(); E next(); //反向迭代列表时,判断是否有元素 boolean hasPrevious(); //返回前一个对象,如果已经是集合的第一个元素,将抛出NoSuchElementException错误 E previous(); //返回下一次调用next方法后,元素的索引 int nextIndex(); //返回下一次调用previous方法后,元素的索引 int previousIndex(); // Modification Operations void remove(); void set(E e); void add(E e); }
Set接口和Collection接口的方法一样,这里Java为什么要定义一个新的接口?是为了从概念上区分集合与集,方面扩展。
SortedSet和SortedMap接口,顾名思义给开发者暴露了排序的方法,并可以返回某个范围内的子集
(6)SortedSet的源码如下:
public interface SortedSet<E> extends Set<E> { //用于排序的方法,参考后续章节具体实现类 Comparator<? super E> comparator(); //下面三个方法,返回给定范围内的子SortedSet集 SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> headSet(E toElement); SortedSet<E> tailSet(E fromElement); E first(); E last(); }
(7)SortedMap的源码如下:
public interface SortedMap<K,V> extends Map<K,V> { //用于排序的方法,参考后续章节具体实现类 Comparator<? super K> comparator(); //下面三个方法,返回给定范围内的子SortedMap SortedMap<K,V> subMap(K fromKey, K toKey); SortedMap<K,V> headMap(K toKey); SortedMap<K,V> tailMap(K fromKey); //下面三个方法和Map接口中方法一样,参考Map接口源码 Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet(); }
Java SE6引入了NavigableSet和NavigableMap接口,用来在有序集和Map中查找遍历方法
(8)NavigableSet源码如下:
public interface NavigableSet<E> extends SortedSet<E> { E lower(E e); E floor(E e); ....... //下面三个方法主要返回给定范围内的子NavigableSet,boolean 标志是否包括边界值 NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive); NavigableSet<E> headSet(E toElement, boolean inclusive); NavigableSet<E> tailSet(E fromElement, boolean inclusive); //下面三个方法和SortedSet接口中方法一样,参考SortedSet接口源码 SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> headSet(E toElement); SortedSet<E> tailSet(E fromElement); }
(9)NavigableMap源码如下:
public interface NavigableMap<K,V> extends SortedMap<K,V> { Map.Entry<K,V> lowerEntry(K key); K lowerKey(K key); Map.Entry<K,V> floorEntry(K key); K floorKey(K key) Map.Entry<K,V> ceilingEntry(K key); ........ //下面三个方法,返回给定范围内的键的NavigableMap,boolean 表示是否包括边界 NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive); NavigableMap<K,V> headMap(K toKey, boolean inclusive); NavigableMap<K,V> tailMap(K fromKey, boolean inclusive); //下面三个方法,与SortedMap方法一样,参考SortedMap源码 SortedMap<K,V> subMap(K fromKey, K toKey); SortedMap<K,V> headMap(K toKey); SortedMap<K,V> tailMap(K fromKey); }
队列是在尾部添加一个元素,在头部删除一个元素。双端队列是在头部和尾部都可以删除元素
(10)Queue的源码如下:
public interface Queue<E> extends Collection<E> { //当执行add往队列中添加元素时,如果队列没有满,则往队列尾部添加元素并返回true,否则add方法抛出异常,offer方法返回false boolean add(E e); boolean offer(E e); //当执行remove移除队列中头部元素时,如果队列不空,则移除头部元素并返回true,否则remove方法抛出异常,poll方法返回false E remove(); E poll(); //当执行element查看队列中头部元素时,如果队列不空,则返回队列中的头部元素,否则element方法抛出异常,peek方法返回null E element(); E peek(); }
(11)Deque(双端队列接口)源码如下:
public interface Deque<E> extends Queue<E> { //当给定的对象添加到双端队列的头部和尾部时,如果队列满了,则前两个方法抛出异常,后两个方法返回false void addFirst(E e); void addLast(E e); boolean offerFirst(E e); boolean offerLast(E e); //当删除双端队列头部和尾部元素时,如果队列为空,则前两个方法抛出异常,后两个方法返回null E removeFirst(); E removeLast(); E pollFirst(); E pollLast(); //当查询双端队列头部和尾部元素时,如果队列为空,则前两个方法抛出异常,后两个方法返回null E getFirst(); E getLast(); E peekFirst(); E peekLast(); boolean removeFirstOccurrence(Object o); boolean removeLastOccurrence(Object o); // *** Queue methods *** //参考Queue 中的add、offer方法说明 boolean add(E e); boolean offer(E e); //参考Queue 中的remove、poll方法说明 E remove(); E poll(); //参考Queue 中的element、peek方法说明 E element(); E peek(); // *** Stack methods *** void push(E e); E pop(); // *** Collection methods *** //参考Collection 中的方法说明 boolean remove(Object o); boolean contains(Object o); public int size(); Iterator<E> iterator(); Iterator<E> descendingIterator(); }
RandomAccess接口用于监测List随机访问的效率,该接口没有方法,ArrayList继承了该接口。
(12)RandomAccess源码:
public interface RandomAccess { }
2. Java集合类
前面的Java集合接口中有大量的方法,这些方法主要通过抽象类和具体类实现。其中抽象类主要实现接口中一部分通用的方法,具体类针对具体的类型实现具体的方法。下面是Java集合类图:
2.1 Java集合抽象类
对于公用的方法可在集合抽象类实现,一些具体的方法可抽象化在继承的有具体特征的子类中实现。集合抽象类主要有AbstractCollection、AbstractMapAbstractList、AbstractSet、AbstractQueue、AbstractSequentialList
这里以AbstractCollection源码为例分析一下:
AbstractCollection的源码如下:
public abstract class AbstractCollection<E> implements Collection<E> { protected AbstractCollection() { } // Query Operations //Collection接口中方法,可根据不同的集合,具体实现。 //迭代器方法和集合大小方法抽象。 public abstract Iterator<E> iterator(); public abstract int size(); //下面所有的方法都在抽象类中实现 public boolean isEmpty() { return size() == 0; } //用迭代器,访问逐次访问集合中的元素,判断是否包含给定的对象 public boolean contains(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) if (it.next()==null) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } //逐次访问集合中的元素,转换集合中对象为数组 public Object[] toArray() { //根据集合大小定义数组 Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) // fewer elements than expected return Arrays.copyOf(r, i); r[i] = it.next(); } return it.hasNext() ? finishToArray(r, it) : r; } public <T> T[] toArray(T[] a) { // Estimate size of array; be prepared to see more or fewer elements int size = size(); T[] r = a.length >= size ? a : (T[])java.lang.reflect.Array .newInstance(a.getClass().getComponentType(), size); Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) { // fewer elements than expected if (a != r) return Arrays.copyOf(r, i); r[i] = null; // null-terminate return r; } r[i] = (T)it.next(); } return it.hasNext() ? finishToArray(r, it) : r; } //Integer.MAX_VALUE是int整形的最大取值2的31次方-1,这个常量用来控制集合的最大容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static <T> T[] finishToArray(T[] r, Iterator<?> it) { int i = r.length; while (it.hasNext()) { int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1) + 1; // overflow-conscious code if (newCap - MAX_ARRAY_SIZE > 0) newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T)it.next(); } // trim if overallocated return (i == r.length) ? r : Arrays.copyOf(r, i); } //返回集合的最大容量值 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } // 添加对象方法实现 public boolean add(E e) { throw new UnsupportedOperationException(); } //移除对象方法实现 public boolean remove(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) { if (it.next()==null) { it.remove(); return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; } //批量操作方法实现 //判断传入集合是否被包含方法实现 public boolean containsAll(Collection<?> c) { for (Object e : c) if (!contains(e)) return false; return true; } //添加传入集合方法实现 public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; } //移除传入集合方法实现 public boolean removeAll(Collection<?> c) { boolean modified = false; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true; } } return modified; } //实现与传入集合求交集方法 public boolean retainAll(Collection<?> c) { boolean modified = false; Iterator<E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { it.remove(); modified = true; } } return modified; } //对象转换为字符串 public String toString() { Iterator<E> it = iterator(); //如果集合中对象为null,返回"[]" if (! it.hasNext()) return "[]"; //拼接字符串 StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } } }
2.2 Java集合具体实现类
我们项目中经常使用的具体类(Java集合类图中具体类)主要有LinkedList、ArrayList、HashSet、TreeSet、PriorityQueue、Array、Deque、HashMap、TreeMap,这些类的源码解析,见后续章节的分析;下面是Java集合具体类的主要特征,如下表:
相关文章推荐
- 三.学习数据结构之链表(离散存储)
- 数据结构--图的理解:深度优先和广度优先遍历及其 Java 实现
- java 中的JDK封装的数据结构和算法解析(集合类)----链表 List 之 Vector (向量)
- 数据结构:线性表的链式存储
- 数据结构:线性表的顺序存储
- java 实现数据结构之线性表
- 数据结构实现之Bag背包
- 学习笔记------数据结构(C语言版)栈应用 括号匹配
- 优先队列——斜堆
- 算法与数据结构学习资源大搜罗——良心推荐
- 树的重心求法POJ3107
- 学习笔记------数据结构(C语言版)进制转换
- 使用XML文件输入和输出和YAML文件 目标 你会发现以下问题的答案: 如何打印和阅读文本条目文件和OpenCV使用YAML或XML文件? 如何为OpenCV做同样的数据结构?
- 学习笔记------数据结构(C语言版)栈的顺序存储
- 【数据结构与算法】【算法】一些算法
- 【数据结构与算法】【算法】一些算法
- 【数据结构与算法】【算法】一些算法
- 【数据结构与算法】【算法】一些算法
- 【数据结构与算法】【算法】一些算法
- 【数据结构与算法】【算法】一些算法