- 浏览: 407187 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (325)
- 神经网络 (1)
- javascript (11)
- 数据结构 (2)
- 计算机图形学 (11)
- 模式识别 (1)
- 前端开发 (14)
- 机器学习 (11)
- ios开发 (50)
- Python (9)
- HTML5 (4)
- 计算机视觉 (9)
- 数字图像处理 (7)
- 架构设计 (19)
- 数据库设计 (9)
- 算法设计 (59)
- Java (37)
- 其他 (3)
- 游戏开发 (5)
- c++ (17)
- Linux (3)
- TCP/IP (2)
- Flex (41)
- 健康 (6)
- AI (2)
- 工具 (1)
- 数据挖掘 (1)
- 性能优化 (6)
- 综合 (2)
- 网络通信 (12)
- Android (2)
- UML (3)
- 软件设计 (11)
- 编程经验 (7)
- J2EE (1)
- 多媒体技术 (3)
- 数学 (7)
- php (4)
- 设计 (1)
- CS (2)
- 计算机理论 (1)
- 信息安全 (1)
最新评论
-
ahead_zhan:
good good good
flex3控件_ModuleLoader -
lonerzf:
好样的。非常感谢楼主
OpenCV视频教程整理 -
lonerzf:
好样的。谢谢~
OpenCV视频教程整理 -
coding1688:
博主说的不错,我在实现瀑布流布局时也用的masonry插件,有 ...
Javascript 瀑布流式布局及其动态效果的实现 -
snowolf:
除非玩游戏,不然没啥win的事情,或者用win的银行客户端,通 ...
macbook安装操作系统的机理分析
对于很多 Java 开发人员来说,Java Collections API 是标准 Java 数组及其所有缺点的一个非常需要的替代品。将 Collections 主要与 ArrayList
联系到一起本身没有错,但是对于那些有探索精神的人来说,这只是 Collections 的冰山一角。
关于本系列
您觉得自己懂 Java 编程?事实上,大多数程序员对于 Java 平台都是浅尝则止,只学习了足以完成手头上任务的知识而已。在本 系列 中,Ted Neward 深入挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程挑战。
虽然 Map
(以及它的常用实现 HashMap
)非常适合名-值对或键-值对,但是没有理由让自己局限于这些熟悉的工具。可以使用适当的 API,甚至适当的 Collection 来修正很多易错的代码。
本文是 5 件事 系列 中的第二篇文章,也是专门讨论 Collections 的 7 篇文章中的第一篇文章,之所以花这么大的篇幅讨论 Collections,是因为这些集合在 Java 编程中是如此重要。首先我将讨论做每件事的最快(但也许不是最常见)的方式,例如将 Array
中的内容转移到 List
。然后我们深入探讨一些较少人知道的东西,例如编写定制的 Collections 类和扩展 Java Collections API。
刚接触 Java 技术的开发人员可能不知道,Java 语言最初包括数组,是为了应对上世纪 90 年代初期 C++ 开发人员对于性能方面的批评。从那时到现在,我们已经走过一段很长的路,如今,与 Java Collections 库相比,数组不再有性能优势。
例如,若要将数组的内容转储到一个字符串,需要迭代整个数组,然后将内容连接成一个 String
;而 Collections 的实现都有一个可用的 toString()
实现。
除少数情况外,好的做法是尽快将遇到的任何数组转换成集合。于是问题来了,完成这种转换的最容易的方式是什么?事实证明,Java Collections API 使这种转换变得容易,如清单 1 所示:
import java.util.*; public class ArrayToList { public static void main(String[] args) { // This gives us nothing good System.out.println(args); // Convert args to a List of String List<String> argList = Arrays.asList(args); // Print them out System.out.println(argList); } } |
注意,返回的 List
是不可修改的,所以如果尝试向其中添加新元素将抛出一个 UnsupportedOperationException
。
而且,由于 Arrays.asList()
使用 varargs 参数表示添加到 List
的元素,所以还可以使用它轻松地用以 new
新建的对象创建 List
。
将一个集合(特别是由数组转化而成的集合)的内容转移到另一个集合,或者从一个较大对象集合中移除一个较小对象集合,这些事情并不鲜见。
您也许很想对集合进行迭代,然后添加元素或移除找到的元素,但是不要这样做。
在此情况下,迭代有很大的缺点:
- 每次添加或移除元素后重新调整集合将非常低效。
- 每次在获取锁、执行操作和释放锁的过程中,都存在潜在的并发困境。
- 当添加或移除元素时,存取集合的其他线程会引起竞争条件。
可以通过使用 addAll
或 removeAll
,传入包含要对其添加或移除元素的集合作为参数,来避免所有这些问题。
Java 5 中加入 Java 语言的最大的便利功能之一,增强的 for 循环,消除了使用 Java 集合的最后一道障碍。
以前,开发人员必须手动获得一个 Iterator
,使用 next()
获得 Iterator
指向的对象,并通过 hasNext()
检查是否还有更多可用对象。从 Java 5 开始,我们可以随意使用 for 循环的变种,它可以在幕后处理上述所有工作。
实际上,这个增强适用于实现 Iterable
接口的任何对象,而不仅仅是 Collections
。
清单 2 显示通过 Iterator
提供 Person
对象的孩子列表的一种方法。 这里不是提供内部 List
的一个引用 (这使 Person
外的调用者可以为家庭增加孩子 — 而大多数父母并不希望如此),Person
类型实现 Iterable
。这种方法还使得 for 循环可以遍历所有孩子。
// Person.java import java.util.*; public class Person implements Iterable<Person> { public Person(String fn, String ln, int a, Person... kids) { this.firstName = fn; this.lastName = ln; this.age = a; for (Person child : kids) children.add(child); } public String getFirstName() { return this.firstName; } public String getLastName() { return this.lastName; } public int getAge() { return this.age; } public Iterator<Person> iterator() { return children.iterator(); } public void setFirstName(String value) { this.firstName = value; } public void setLastName(String value) { this.lastName = value; } public void setAge(int value) { this.age = value; } public String toString() { return "[Person: " + "firstName=" + firstName + " " + "lastName=" + lastName + " " + "age=" + age + "]"; } private String firstName; private String lastName; private int age; private List<Person> children = new ArrayList<Person>(); } // App.java public class App { public static void main(String[] args) { Person ted = new Person("Ted", "Neward", 39, new Person("Michael", "Neward", 16), new Person("Matthew", "Neward", 10)); // Iterate over the kids for (Person kid : ted) { System.out.println(kid.getFirstName()); } } } |
在域建模的时候,使用 Iterable
有一些明显的缺陷,因为通过 iterator()
方法只能那么 “隐晦” 地支持一个那样的对象集合。但是,如果孩子集合比较明显,Iterable
可以使针对域类型的编程更容易,更直观。
您是否曾想过以倒序遍历一个 Collection
?对于这种情况,使用经典的 Java Collections 算法非常方便。
在上面的 清单 2 中,Person
的孩子是按照传入的顺序排列的;但是,现在要以相反的顺序列出他们。虽然可以编写另一个 for 循环,按相反顺序将每个对象插入到一个新的 ArrayList
中,但是 3、4 次重复这样做之后,就会觉得很麻烦。
在此情况下,清单 3 中的算法就有了用武之地:
public class ReverseIterator { public static void main(String[] args) { Person ted = new Person("Ted", "Neward", 39, new Person("Michael", "Neward", 16), new Person("Matthew", "Neward", 10)); // Make a copy of the List List<Person> kids = new ArrayList<Person>(ted.getChildren()); // Reverse it Collections.reverse(kids); // Display it System.out.println(kids); } } |
Collections
类有很多这样的 “算法”,它们被实现为静态方法,以 Collections
作为参数,提供独立于实现的针对整个集合的行为。
而且,由于很棒的 API 设计,我们不必完全受限于 Collections
类中提供的算法 — 例如,我喜欢不直接修改(传入的 Collection 的)内容的方法。所以,可以编写定制算法是一件很棒的事情,例如清单 4 就是一个这样的例子:
class MyCollections { public static <T> List<T> reverse(List<T> src) { List<T> results = new ArrayList<T>(src); Collections.reverse(results); return results; } } |
以上定制算法阐释了关于 Java Collections API 的一个最终观点:它总是适合加以扩展和修改,以满足开发人员的特定目的。
例如,假设您需要 Person
类中的孩子总是按年龄排序。虽然可以编写代码一遍又一遍地对孩子排序(也许是使用 Collections.sort
方法),但是通过一个 Collection
类来自动排序要好得多。
实际上,您甚至可能不关心是否每次按固定的顺序将对象插入到 Collection
中(这正是 List
的基本原理)。您可能只是想让它们按一定的顺序排列。
java.util
中没有 Collection
类能满足这些需求,但是编写一个这样的类很简单。只需创建一个接口,用它描述 Collection
应该提供的抽象行为。对于 SortedCollection
,它的作用完全是行为方面的。
public interface SortedCollection<E> extends Collection<E> { public Comparator<E> getComparator(); public void setComparator(Comparator<E> comp); } |
编写这个新接口的实现简直不值一提:
import java.util.*; public class ArraySortedCollection<E> implements SortedCollection<E>, Iterable<E> { private Comparator<E> comparator; private ArrayList<E> list; public ArraySortedCollection(Comparator<E> c) { this.list = new ArrayList<E>(); this.comparator = c; } public ArraySortedCollection(Collection<? extends E> src, Comparator<E> c) { this.list = new ArrayList<E>(src); this.comparator = c; sortThis(); } public Comparator<E> getComparator() { return comparator; } public void setComparator(Comparator<E> cmp) { comparator = cmp; sortThis(); } public boolean add(E e) { boolean r = list.add(e); sortThis(); return r; } public boolean addAll(Collection<? extends E> ec) { boolean r = list.addAll(ec); sortThis(); return r; } public boolean remove(Object o) { boolean r = list.remove(o); sortThis(); return r; } public boolean removeAll(Collection<?> c) { boolean r = list.removeAll(c); sortThis(); return r; } public boolean retainAll(Collection<?> ec) { boolean r = list.retainAll(ec); sortThis(); return r; } public void clear() { list.clear(); } public boolean contains(Object o) { return list.contains(o); } public boolean containsAll(Collection <?> c) { return list.containsAll(c); } public boolean isEmpty() { return list.isEmpty(); } public Iterator<E> iterator() { return list.iterator(); } public int size() { return list.size(); } public Object[] toArray() { return list.toArray(); } public <T> T[] toArray(T[] a) { return list.toArray(a); } public boolean equals(Object o) { if (o == this) return true; if (o instanceof ArraySortedCollection) { ArraySortedCollection<E> rhs = (ArraySortedCollection<E>)o; return this.list.equals(rhs.list); } return false; } public int hashCode() { return list.hashCode(); } public String toString() { return list.toString(); } private void sortThis() { Collections.sort(list, comparator); } } |
这个实现非常简陋,编写时并没有考虑优化,显然还需要进行重构。但关键是 Java Collections API 从来无意将与集合相关的任何东西定死。它总是需要扩展,同时也鼓励扩展。
当然,有些扩展比较复杂,例如 java.util.concurrent
中引入的扩展。但是另一些则非常简单,只需编写一个定制算法,或者已有 Collection
类的简单的扩展。
扩展 Java Collections API 看上去很难,但是一旦开始着手,您会发现远不如想象的那样难。
和 Java Serialization 一样,Java Collections API 还有很多角落等待有人去探索 —正因为如此,我们还不准备结束这个话题。在 5 件事 系列 的下一篇文章中,将可以看到用 Java Collections API 做更多事情的 5 种新的方式。
<!-- CMA ID: 491184 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
发表评论
-
多种加密算法实现(JAVA)
2013-10-24 09:18 1616有短句“Sun Yat-sen University is ... -
断点续传的原理
2013-05-07 19:53 826转自:http://www.ibm.com/develope ... -
《JAVA与模式》之调停者模式
2012-06-21 20:06 630参考:http://www.cnblo ... -
Java 线程池的原理与实现
2011-10-23 15:48 691参考: http://www.blogjava.ne ... -
Java中读取字节流并按指定编码转换成字符串的方法
2011-05-21 11:22 1447参考: http://www.blogjava.net/pen ... -
字节流编码获取原来这么复杂,但也很简单
2011-05-21 11:02 1498参考:http://www.cnblogs ... -
使用Java.util.zip下的zipOutStream和zipInStream对字节流进行压缩和解压缩
2011-05-21 10:08 1714参考:http://www.blogjava.net/ushe ... -
ActionScript与Java类型对应表
2011-05-21 09:46 1029当你使用AMF格式进行RemoteObject 调用时,肯定会 ... -
基于red5的在线视频录制实例和详细注释
2011-05-14 23:03 1575参考:http://www.ccvita.com/130.ht ... -
Java 中几种查找算法
2011-05-12 10:31 1463顺序查找说明:顺序查找适合于存储结构为顺序存储或链接存储的线性 ... -
Converting data from Java to ActionScript
2011-05-07 14:23 976On the client side, the ide ... -
java大整数相加及相乘
2011-05-04 18:34 1483import java.io.BufferedInputStr ... -
.org.hibernate.ObjectNotFoundException: No row with the given identifier exists
2011-04-20 18:09 1130说到底,就是外键关联引起的问题。 问题产生原因:有一个 ... -
java.util.ConcurrentModificationException
2011-04-19 10:07 573一般来说这个异常是容器类在遍历的时候被修改时抛出的。比 ... -
Spring+Hibernate+Flex,update、delete操作无法持久到数据库的解决办法
2011-04-17 21:42 1412这个解决办法就是才有事务机制了。。。 我是spring ... -
hibernate 注解 一对多 唯一索引
2011-04-17 02:00 2824今天被hibernate和mysql整了一下,切身感受到索引的 ... -
精通Hibernate——映射一对多关联关系
2011-04-17 01:38 1010在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据U ... -
junit实现opensessionInView保持session
2011-04-11 10:00 825参考:http://allenwei.iteye.com/bl ... -
Hibernate中cascade与inverse属性详解
2011-04-07 10:57 1047原文: 忘记存了..... ... -
HIbernate注解
2011-04-07 10:37 895Hibernate注解 文章分类:Web前端 @o ...
相关推荐
### 关于 Java Collections API 您不知道的 5 件事 #### 1. Collections 比数组更好 在 Java 的早期阶段,为了回应 C++ 开发者对于性能的批评,Java 引入了数组这一概念。然而,随着时间的发展,Java 的 ...
这篇博客的第二部分将深入探讨关于Collections API的一些不那么为人所知的知识点,旨在帮助开发者更好地理解和利用这些功能。下面我们将详细解析这五个知识点。 1. **`Collections.sort()` 方法的内部实现** `...
《Java Collections》是Apress出版社出版的一本专著,它深入浅出地讲解了Java Collections框架,这是一套用于管理对象集合的强大的API。这本书针对Java程序员,无论你是初学者还是经验丰富的开发者,都能从中...
根据提供的文件信息,我们可以推断出这是一本关于Java Collections的书籍,作者为John Zukowski。下面将基于这些信息来生成相关的Java Collections知识点。 ### Java Collections 概览 #### 一、简介 Java ...
Java API是Java编程语言的核心组成部分,它包含了各种预定义的类和接口,为开发者提供了丰富的功能,使得开发者能够构建复杂的软件系统。Java API_5.0中文版是Sun Microsystems(后被Oracle收购)官方发布的文档,是...
Java API 1.6 和 1.7 是Java开发的关键组成部分,它们包含了Java标准库的详细文档,这些库是编写Java应用程序和服务器端程序的基础。这两个版本在Java发展历程中占据了重要地位,引入了许多新特性,优化了性能,并...
10. **Stream API**: 自Java 8引入的Stream API为处理集合提供了新的方式,支持函数式编程风格,如过滤、映射、归约等操作。 了解和熟练使用Java集合框架是成为一名合格Java开发者的必要条件。通过深入学习这些知识...
"JavaScript 5.CHM"则是关于JavaScript这门脚本语言的API参考,虽然不是Java的一部分,但常常与Java一起使用,特别是在Web开发中,用于实现客户端的动态交互。 "Servlets and JSP API Documentation.chm"包含了...
异常处理是 Java 代码中不可或缺的部分,通过 `try-catch-finally` 块来捕获和处理异常。`Exception` 是所有检查性异常的基类,而 `RuntimeException` 表示非检查性异常。 6. **反射机制** Java 1.6 的反射机制...
Java API(Application Programming Interface)是Java编程语言的核心组成部分,它为开发者提供了丰富的类库和接口,使得开发人员能够高效地构建各种类型的应用程序。在Java世界中,API涵盖了从基本的输入/输出到...
1. **Java核心技术**:文档涵盖了Java的基础类库,如集合框架(Collections Framework)、IO流(Input/Output Streams)、网络编程(Networking)、多线程(Multithreading)和异常处理(Exception Handling)。...
以上只是Java 1.8 API中部分关键知识点的概述,实际文档中还有更多关于异常处理、网络编程、XML处理、数据库连接等方面的详细内容。开发者应充分利用API文档,深入学习,提升自己的Java编程技能。
在Java 6.0 API中,主要包含以下几个关键部分: 1. **基础类库**:如`java.lang`包,包含基本类型、对象、异常处理等核心类,如`Object`、`String`、`Exception`。 2. **集合框架**:在`java.util`包中,包括`...
Java API,全称为Java Application Programming Interface,是Java语言的核心组成部分,为开发者提供了大量的预定义类、接口和方法,使得程序员能够便捷地进行系统级编程。Java API覆盖了网络通信、文件操作、多线程...
标签:eclipse、collections、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...
Java集合框架是Java编程语言中的一个核心组成部分,它为数据存储、检索和传输提供了统一的架构。这个框架的设计由著名的大师Josh Bloch提出,并在JavaOne 1998首次公开,目的是为了改善早期Java中仅有的Vector、...
1. **基础类库**:这是Java API的核心,包括`java.lang`包,提供了基本类型转换、异常处理、线程管理等基础功能。例如,`Object`是所有类的父类,`String`用于字符串操作,`Integer`和`Double`等是基本类型的包装类...