多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## [基本概念](https://lingcoder.gitee.io/onjava8/#/book/12-Collections?id=%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5) Java集合类库采用“持有对象”(holding objects)的思想,并将其分为两个不同的概念,表示为类库的基本接口: 1. **集合(Collection)**:一个独立元素的序列,这些元素都服从一条或多条规则。**List**必须以插入的顺序保存元素,**Set**不能包含重复元素,**Queue**按照*排队规则*来确定对象产生的顺序(通常与它们被插入的顺序相同)。 2. **映射(Map)**: 一组成对的“键值对”对象,允许使用键来查找值。**ArrayList**使用数字来查找对象,因此在某种意义上讲,它是将数字和对象关联在一起。**map**允许我们使用一个对象来查找另一个对象,它也被称作*关联数组*(associative array),因为它将对象和其它对象关联在一起;或者称作*字典*(dictionary),因为可以使用一个键对象来查找值对象,就像在字典中使用单词查找定义一样。**Map**是强大的编程工具。 尽管并非总是可行,但在理想情况下,你编写的大部分代码都在与这些接口打交道,并且唯一需要指定所使用的精确类型的地方就是在创建的时候。因此,可以像下面这样创建一个**List**: ~~~ List<Apple> apples = new ArrayList<>(); ~~~ 请注意,**ArrayList**已经被向上转型为了**List**,这与之前示例中的处理方式正好相反。使用接口的目的是,如果想要改变具体实现,只需在创建时修改它就行了,就像下面这样: ~~~ List<Apple> apples = new LinkedList<>(); ~~~ 因此,应该创建一个具体类的对象,将其向上转型为对应的接口,然后在其余代码中都是用这个接口。 这种方式并非总是有效的,因为某些具体类有额外的功能。例如,**LinkedList**具有**List**接口中未包含的额外方法,而**TreeMap**也具有在**Map**接口中未包含的方法。如果需要使用这些方法,就不能将它们向上转型为更通用的接口。 **Collection**接口概括了*序列*的概念——一种存放一组对象的方式。下面是个简单的示例,用**Integer**对象填充了一个**Collection**(这里用**ArrayList**表示),然后打印集合中的每个元素: ~~~ // collections/SimpleCollection.java import java.util.*; public class SimpleCollection { public static void main(String[] args) { Collection<Integer> c = new ArrayList<>(); for(int i = 0; i < 10; i++) c.add(i); // Autoboxing for(Integer i : c) System.out.print(i + ", "); } } /* Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, */ ~~~ 这个例子仅使用了**Collection**中的方法(即`add()`),所以使用任何继承自**Collection**的类的对象都可以正常工作。但是**ArrayList**是最基本的序列类型。 `add()`方法的名称就表明它是在**Collection**中添加一个新元素。但是,文档中非常详细地叙述到`add()`“要确保这个**Collection**包含指定的元素。”这是因为考虑到了**Set**的含义,因为在**Set**中,只有当元素不存在时才会添加元素。在使用**ArrayList**,或任何其他类型的**List**时,`add()`总是表示“把它放进去”,因为**List**不关心是否存在重复元素。 可以使用*for-in*语法来遍历所有的**Collection**,就像这里所展示的那样。在本章的后续部分,还将学习到一个更灵活的概念,*迭代器*。