Java 容器集合框架概览

Java Collections Framework

 

集合的概念

  集合collection,有时叫做容器container,把多个元素组成一个单元。

  早期的Java (pre-1.2) 中包含了Vector, Hashtable, 和array,但是没有包含一个统一的集合框架。

  Java Collections Framework是一个统一的框架,为了表现和操纵集合。

  所有的collections frameworks包括:接口(Interfaces)、实现(Implementations)和算法(Algorithms)。

 

泛型和类型安全的容器

  使用Java SE5之前的容器的一个主要问题就是编译器允许你向容器中插入不正确的类型。

  比如ArrayList,用add()插入对象,因为ArrayList保存的是Object,所以可以添加各种类型的对象,在编译期和运行时都不会产生问题。

  当你用get()方法取出对象时,得到的只是Object类的引用,必须使用强制类型转换将其转换为特定的类型。在运行时,当你试图将一个类的对象转换为另一个类的对象时,就会得到一个异常。

  可以在容器的尖括号中包含类型参数,指定容器实例可以保存的类型。

  通过使用泛型,就可以在编译期防止将错误类型的对象放置到容器中。

  这样的另外一个好处是,在将元素取出的时候,类型转换也不再是必须的了。因为容器知道它保存的是什么类型,因此它会在调用get()时替你执行转型。

 

接口

  核心的集合接口封装了不同类型的集合。如下图所示:

  

 核心集合接口

  所有的核心接口都是泛型的,比如Collection接口:

  public interface Collection<E>

  <E>说明声明实例的时候需要指明对象类型,这样编译器就可以在编译期进行一个类型检查,减少运行时错误。

 

Collection

  一个Collection代表了一组对象,这些对象被称为其元素(elements)。

  这个接口提供了一些方法,告诉你有多少元素(size, isEmpty),检查一个对象是否包含在集合里(contains),为集合增加或者减少元素(add, remove),或者为集合提供迭代器(iterator)。

Set

  一个不包含重复元素的集合。这个接口对数学中的集合的抽象概念进行了建模。

List

  List定义一个有顺序的集合,有时也被称作一个序列(sequence)。List可以包含重复的元素。

Queue

    通常,Queue中的元素都是按照FIFO (first-in-first-out)的方式,但是这不是必须的。一些优先级队列元素,按照它们的值排列。但是不管使用了什么排序方式,调用remove或poll方法时,移除的都是队列头元素。在FIFO队列中,新元素总是被插在队尾,但是其他类型的队列可能会使用不同的排列方式。

Map

  Map中存储的是键值对的映射。一个Map不能包含重复的key,一个key可以对应至多一个值。

SortedSet和SortedMap

  还有两个核心的接口是排序版本的Set和Map:SortedSet和SortedMap。SortedSet的元素是按照升序排列的,SortedMap是按照键的升序排列键值对的。

 

实现 (Implementations)

  通用目的的实现: 

Interfaces

Set

List

Map

Hash table Implementations

HashSet

 

HashMap

Resizable array Implementations

 

ArrayList

 

Tree Implementations

TreeSet

 

TreeMap

Linked list Implementations

 

LinkedList

 

Hash table + Linked list Implementations

LinkedHashSet

 

LinkedHashMap

  

 

  Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
  

  1.Collection

  一个独立元素的序列,这些元素都服从一条或者多条规则。

  List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。

  有两种类型的List:

  ArrayList,它长于随机访问元素,但是在List的中间插入和删除元素时较慢。

  LinkedList,它在随机访问方面相对比较慢,但是它进行插入和删除代价较低。

  Set:

  HashSet、TreeSet、和LinkedHashSet都是Set,每个相同的项只保存一次。

  HashSet是最快的获取元素方式,存储的顺序看起来并无实际意义;TreeSet按照比较的结果升序保存对象;LinkedHashSet按照被添加的顺序保存对象。

  

  2.Map

  一组成对的“键值对”对象,允许你使用键来查找值。

  映射表允许我们使用另一个对象来查找某个对象,它也被称为“关联数组”,因为它将某些对象与另外一些对象关联在了一起,或者被称为“字典”。

  HashMap、TreeMap、和LinkedHashMap都是Map。

  HashMap提供了最快的查找技术,也没有按照任何明显的顺序来保存其元素。

  TreeMap按照比较结果的升序保存键。

  LinkedHashMap则按照插入顺序保存键,同时还保留了HashMap的查询速度。

  

  略去一些类和接口,一个简化版的类图关系如下:

   

 

 

算法

  Collections 类提供了很多可复用的算法,它们都是静态方法的形式。

  有代表性的几个算法:

排序Sorting

  排序算法将集合重新排序,按照升序排列。

  有两种形式:

  sort(List<T> list)和sort(List<T> list, Comparator<? super T> c),前者按照元素的自然顺序排列,后者按照参数提供的具体的比较器进行排列。

  关于排序顺序可见:

  http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html

  排序算法使用的是归并算法(merge sort),因为它快速并且稳定(不会交换相等元素的位置),快速排序不稳定,并且也不能保证log(n)的效率。

 

洗牌Shuffling

  shuffle算法打乱元素的顺序,制造一种随机无序的结果。

  shuffle算法也有两种形式,一种使用默认的随机源,另一种使用用户传入的随机源(a source of randomness)。

 

常规数据操作Routine Data Manipulation

  reverse:将List中的元素顺序反转。

  fill:将每一个元素都用指定的值填充。

  copy:拷贝源数据到目标数据List,目标List必须更长,这样目标List中前半段元素将被覆写,剩下的元素保持原状。

  swap:交换List中两个指定位置的元素。

  addAll:把指定的元素全都加入到指定的集合中去。

 

查找Searching

  binarySearch算法在一个已经有序的List中用二分法查找一个特定的元素。

  这个算法有两种形式,第一种传入一个List和一个指定的元素,这种形式假定这个List是按照其自然顺序的升序排列的。第二种形式还需要多传入一个比较器Comparator,并且假定List已经按照该比较器进行过排序,为升序。可以在binarySearch方法调用前先调用sort算法。

  如果查找成功,返回索引,如果不成功,返回值是(-(insertion point) - 1),插入点(insertion point)是这个值应该插入的地方。这样就保证了如果查找成功,那么返回值是大于等于0的。

  下面这个形式可以将查找失败的元素插入集合:

int pos = Collections.binarySearch(list, key);

if (pos < 0)

   l.add(-pos-1);

 

组成Composition

  对于集合的构成查询也存在一些方法:

  frequency:计算某个特定元素在集合中出现的次数。

  disjoint:判断两个集合是否分离,即它们是不是不含公共元素。

 

找极值Finding Extreme Values

  min和max方法分别返回集合中的最小和最大元素。

  它们都有两种形式,一种形式仅传入集合,然后根据元素的自然顺序返回极值;另一种形式需要再传入一个比较器Comparator,根据比较器设定的规则来返回极值。

 


参考资料

  Java SE Documentation: The Collections Framework

  http://docs.oracle.com/javase/7/docs/technotes/guides/collections/index.html

  The Java Tutorials: Lesson: Interfaces

  http://docs.oracle.com/javase/tutorial/collections/interfaces/index.html

  The Java Tutorials: Lesson: Implementations

  http://docs.oracle.com/javase/tutorial/collections/implementations/index.html

  The Java Tutorials: Lesson: Algorithms

  http://docs.oracle.com/javase/tutorial/collections/algorithms/index.html

--------------------------

集合中存放的依然是对象的引用而不是对象本身。

  集合中存放的不能是原生数据类型,需要使用原生数据类型的包装类。

  当遍历集合中的元素时,可以使用迭代器。

  Collections这个类中包含了一系列的静态方法,用于操纵集合或者返回集合。

 

ArrayList和LinkedList的比较

  ArrayList和LinkedList类都是List接口的实现类。

  ArrayList底层采用数组实现,LinkedList底层采用双向链表实现。

  插入、删除操作,LinkedList的效率更高。

  当执行搜索操作时,ArrayList比较好。

  当向ArrayList添加一个对象时,实际上就是将该对象放置到了ArrayList底层所维护的数组当中;当向LinkedList中添加一个对象时,实际上LinkedList内部会生成一个Entry对象,该Entry对象的结构为:

 

Entry
{
    Entry previous;
    Object element;
    Entry next;
}

 

  其中的Object类型的元素element就是我们向LinkedList中所添加的元素,然后Entry又构造好了向前与向后的引用previous、next,最后将生成的这个Entry对象加入到了链表当中。

  换句话说,LinkedList中所维护的是一个个的Entry对象。

 

Set接口

实现类HashSet

  元素是无序的,且不允许重复。

  当使用add()方法把元素加入到Set中去时,会返回一个布尔值。当集合中不存在这个元素时,元素加入,元素加入成功时,返回true; 当集合中已经存在相同元素时,不加入当前元素,add()方法返回false

  当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致;如果不一致,直接加进去;如果一致,再进行equals()方法的比较,equals()方法如果返回true,表示对象已经加进去了,就不会增加新的对象,否则加进去。

  equals()方法和hashCode()方法都是Object类中的方法,如果没有进行覆写,则使用Object类中的实现。

  如果我们重写equals()方法,那么也要重写hashCode()方法,反之亦然。

  关于这两个方法的讨论可以参见Object类的讨论:

  http://www.cnblogs.com/mengdd/archive/2013/01/03/2842809.html

  Eclipse提供了自动生成hashCode()方法和equals()方法的功能:右键>Source>Generate hashCode() and equals()。

 

接口SortedSet

  SortedSet继承了Set接口,SortedSet的实现类是TreeSet。

  (可以参见前文Java 容器集合框架概览中的集合框架类图)。

  放入集合中的元素按照一定的顺序排列起来,加入元素时要求元素必须是可比较的,否则加入第二个元素时会抛出ClassCastException异常,因为它无法和之前已经存在的元素比较。

  TreeSet的构造方法中有一个

  TreeSet(Comparator<? super E> comparator)

  形式的方法,可以自己定义一个比较的方法传入:用一个类实现Comparator接口,然后重新定义其中的compare(T o1, T o2)方法,最后将这个类的对象传入上述TreeSet的构造方法。

 

Map

  Map映射,将键映射到它的值上。不能包含重复的键,每一个键最多可以映射到一个值。

  将键值对放入集合,用put方法:V put(K key, V value)。

  如果之前已经包含这个key,则用新的值更新旧的值。

  Map是一个接口,它的一个实现类是HashMap<K,V>。

  取出值,用get方法,参数是Key,返回时Value。如果不包含这个键的映射,则返回null。

  keySet()方法返回键的集合。返回Set<K>。

  values()方法返回值的集合。返回Collection<V>。

  说明键不能重复,但是值可以重复。

 

Interface Map.Entry<K,V>

  entrySet()方法返回map映射的集合。

 

TreeMap

  TreeMap是Map接口的另一个实现类,它的特点是对Key进行了比较,并且按照Key的顺序存放。

 

HashSet和HashMap

  HashSet底层使用HashMap实现的。当使用add方法将对象添加到Set当中时,实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)。

    // Dummy value to associate with an Object in the backing Map

    private static final Object PRESENT = new Object();

 

  HashMap的底层实现:

  HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组当中。

  当向HashMap中put一对键值对时,它会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。

  如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,则将该对象放到数组当中,然后将数组中该位置以前存在的那个对象链接到此对象的后面。(哈希链表)。

 

  Hashtable和Vector都是比较旧时代的东东,所以一般不用。

  Properties是Hashtable的一个子类,经常会被使用。

 

参考资料

  张龙老师视频教程。

  Java容器集合类的区别用法:

  http://www.cnblogs.com/sunliming/archive/2011/04/05/2005957.html

  Java集合类源码分析汇总:

  http://www.cnblogs.com/hzmark/archive/2013/01/05/JavaCollectionSum.html

  Java集合总结汇总(链接)

  http://www.cnblogs.com/Bob-FD/archive/2012/09/20/2695458.html

 

  几个关键接口和类的官方文档:

  Interface Collection<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html

  Interface List<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/List.html

  Class ArrayList<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

  Class LinkedList<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html

  Interface Set<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/Set.html

  Class HashSet<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html

  Class TreeSet<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html

  Interface Map<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

  Class HashMap<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html

  Class TreeMap<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html


======================================

 集合转换

1.list转set

Set set = new HashSet(new ArrayList()); 


2.set转list

List list = new ArrayList(new HashSet());

3.数组转为list

List stooges = Arrays.asList("Larry""Moe""Curly"); 


此时stooges中有有三个元素。 
4.数组转为set 
int[] a = { 1, 2, 3 }; 

Set set = new HashSet(Arrays.asList(a));

5.map的相关操作。

Java代码  复制代码
  1. Map map = new HashMap();      
  2. map.put("1""a");      
  3. map.put('2''b');      
  4. map.put('3''c');      
  5. System.out.println(map);      
  6. // 输出所有的值      
  7. System.out.println(map.keySet());      
  8. // 输出所有的键      
  9. System.out.println(map.values());      
  10. // 将map的值转化为List      
  11. List list = new ArrayList(map.values());      
  12. System.out.println(list);      
  13. // 将map的值转化为Set      
  14. Set set = new HashSet(map.values());      
  15. System.out.println(set);    

6.list转数组

Java代码  复制代码
  1. List list = Arrays.asList("a","b");      
  2. System.out.println(list);      
  3.               
  4. String[] arr = (String[])list.toArray(new String[list.size()]);      
  5. System.out.println(Arrays.toString(arr));    

内容概要:本文是一篇面向初学者和技术爱好者的《SQL 入门与实战》指南,系统介绍了 SQL 的基本概念、功能及其应用场景。文章首先解释了 SQL 是一种用于操作关系型数据库的语言,能够执行数据的存储、查询、更新、删除以及表结构管理等操作。接着详细列举了基础语法,包括 SELECT、INSERT、UPDATE 和 DELETE 等语句的具体用法,并对常用的函数进行了分类说明,如聚合函数、字符串函数、时间函数等。此外,还深入探讨了多表连接、分组与聚合、子查询和窗口函数等进阶语法技巧。为了帮助读者更好地掌握 SQL,文中提供了从初级到高级的学习路线,并通过实际案例展示了 SQL 在后端 API 查询、数据报表分析、数据清洗与迁移等场景中的应用。最后简要比较了几种常见的数据库系统特性,强调了 SQL 在数据处理领域的重要性。 适合人群:适合初学者、实用派和技术爱好者,尤其是那些希望快速上手 SQL 并应用于实际工作的人员,如前端、后端、测试工程师、数据分析师和产品经理等。 使用场景及目标:①作为 SQL 学习入门资料,帮助读者理解 SQL 的基本概念和语法;②指导读者进行 SQL 编程实践,掌握数据查询、更新、插入、删除及表结构管理等操作;③为有经验的开发者提供进阶技巧,如多表连接、子查询、窗口函数等;④为从事数据相关工作的人员提供实用工具,提高工作效率。 其他说明:文章不仅涵盖了 SQL 的基础知识,还涉及到了一些高级主题,如事务、索引、视图、触发器等,并给出了进一步学习的书籍和在线资源推荐,鼓励读者通过持续学习来深化对 SQL 的理解和应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值