不论是在c++还是java或者是c#,容器都是编程解决问题的一个利器。现在和大家分享一下java的几个常用容器。
首先,我们先看一下几个常用容器接口之间的关系。
接口Map<K,V>是个独立的接口,它有个子接口SortedMap<K,V>。搞清楚这些接口之间的关系,有利用我们了解类、接口之间的转型。
- 看一下容器的基本概念
JAVA 的容器可以分为两个不同的概念。
1)Collection,一个独立的元素序列。就像上图所示的那样,Collection有3个子接口。它们存储元素的时候,都有一定的规则。List必须按照插入元素的顺序保存元素,Set不能存有重复的元素,Queue按照队列的规则进行保存和输出对象(先进先出)
2)Map,一组成对的“键-值对”对象。它允许你通过键来查找与改键对应的值。
如果大家写的程序大都是和接口打交道并且你用的实现那些接口的子类的功能都是那些接口有的,那么建议大家将对象向上转型为接口,因为这样下面的操作就和上面的实现没有关系了。
比如:List<XXX> list = new ArrayList<XXX>();
我们先看一下List接口及其他的几个实现它的类
第一:ArrayList<T>
它就像一个可变数组,擅长于随机访问。在List中间插入和移除元素时较慢。
第二:LinkedList<T>
它就像一个链表,在插入和删除元素时话费的代价比较小,随机访问它不擅长滴。
我们看一下ArrayList的构造方法和常用的方法。
先看构造方法
ArrayList() 构造一个初始容量为 10 的空列表。 |
ArrayList(Collection<? extendsE> c) 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。 |
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。 |
第一个构造函数的源代码:
public ArrayList() {
this(10);
}
第二个构造函数的源代码:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
第三个构造函数的源代码:
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
List接口常见的方法:
List<E> subList(int fromIndex, int toIndex)
- 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和toIndex 相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作.
- 看一下改方法的源代码:public List<E> subList(int fromIndex, int toIndex) {
return new SubList<E>(this, fromIndex, toIndex);
} - SubList<E>是个内部类,先不管这个内部类的构造函数是怎么样的,我们从this这个参数就可以看出对subString这个函数返回的列表的修改回影响到最原始的那个列表。
-
package com.csdn; import java.util.*; public class Test { /** * @param args */ public static void main(String[] args) { List<String> list = new ArrayList<String>(Arrays.asList("1","2","3")); list.addAll(Arrays.asList("a","b","c")); System.out.println(list); List<String> list1 = list.subList(0, 3); list1.remove(1); System.out.println(list); } }
输出结果:[1, 2, 3, a, b, c]
[1, 3, a, b, c] -
public boolean contains(Object o)
- 如果此列表中包含指定的元素,则返回 true。更确切地讲,当且仅当此列表包含至少一个满足 (o==null ? e==null : o.equals(e)) 的元素e 时,则返回
true。 -
- 指定者:
- 接口
Collection<E>
中的contains
- 指定者:
- 接口
List<E>
中的contains
- 覆盖:
- 类
AbstractCollection<E>
中的contains
-
- 参数:
o
- 测试此列表中是否存在的元素- 返回:
- 如果此列表包含特定的元素,则返回 true
需要注意的是,当使用contains、indexOf、remove方法时,他们都会用到equals方法,所以当你自定义类的时候要覆盖equals方法。
- 如果此列表中包含指定的元素,则返回 true。更确切地讲,当且仅当此列表包含至少一个满足 (o==null ? e==null : o.equals(e)) 的元素e 时,则返回
-
addAll
public boolean addAll(Collection<? extends E> c)
- 按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。如果正在进行此操作时修改指定的 collection ,那么此操作的行为是不确定的。(这意味着如果指定的 collection 是此列表且此列表是非空的,那么此调用的行为是不确定的)。
-
- 指定者:
- 接口
Collection<E>
中的addAll
- 指定者:
- 接口
List<E>
中的addAll
- 覆盖:
- 类
AbstractCollection<E>
中的addAll
-
- 参数:
c
- 包含要添加到此列表中的元素的 collection- 返回:
- 如果此列表由于调用而发生更改,则返回 true
- 抛出:
NullPointerException
- 如果指定的 collection 为 null- 另请参见:
AbstractCollection.add(Object)
addAll
public boolean addAll(int index, Collection<? extends E> c)
- 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。向右移动当前位于该位置的元素(如果有)以及所有后续元素(增加其索引)。新元素将按照指定 collection 的迭代器所返回的元素顺序出现在列表中。
-
- 参数:
index
- 插入指定 collection 中的首个元素的位置索引c
- 包含要添加到此列表中元素的 collection- 返回:
- 如果此列表由于调用而发生更改,则返回 true
- 抛出:
IndexOutOfBoundsException
- 如果索引超出范围 (index < 0 || index > size())NullPointerException
- 如果指定的 collection 为 null
看接口Set
Set不保存重复的元素。就是有重复的元素会被覆盖,因为实现Set接口 的子类是通过调用实现Map接口的子类的操作实现的,它的add操作就是调用XXMap的put函数实现的。Set中常被使用的是测试归属性;可以很容易地查询到某个对象是否在Set中。所有查找就陈伟了Set中最重要的操作。HashSet,它专门对快速查找进行了优化。另外要注意到HashSet 、TreeSet和LinkedHashSet维护存储元素时的顺序都是不一样。HashSet为了实现快速的查找操作,它是用了散列函数。TreeSet将元素存储到红-黑数据结构中(其实是按字典比较大小然后存储的)。LinkedHashSet,也使用了散列函数,但还它存储元素的顺序是用了链表来维护插入元素的顺序。接口Map
Map用来保存键值对的。他也有三个常用的子类,TreeMap HashMap LinkedHashMap.它的操作和Set差不多,,void
clear()
从此映射中移除所有映射关系(可选操作)。boolean
containsKey(Object key)
如果此映射包含指定键的映射关系,则返回true。boolean
containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回true。int
hashCode()
返回此映射的哈希码值。boolean
isEmpty()
如果此映射未包含键-值映射关系,则返回true。int
size()
返回此映射中的键-值映射关系数。