原文链接:http://www.blogbus.com/dreamhead-logs/236028457.html

你应该更新的Java知识之常用程序库(一)
你应该更新的Java知识之常用程序库(二)
你应该更新的Java知识之构建工具
你应该更新的Java知识之Observer
你应该更新的Java知识之集合初始化
你应该更新的Java知识之集合操作
你应该更新的Java知识之惰性求值
你应该更新的Java知识之Optional
你应该更新的Java知识之Optional高级用法

在传统的Java里,为了表示一个集合,我们常常会写出这样的代码:

public class People {private List people;public void setPeople(List people) {this.people = people;}public List getPeople() {return this.people;}...
}

严格说来,这样的代码存在缺陷。虽然貌似List被封装到People里,但实际上,这个List的引用却暴露在外面,这个类的用户可以轻松地拿到List的引用,随意修改。所以,下面是一种更严谨的写法:

public class People {private List people;public void setPeople(List people) {this.people.addAll(people);}@SuppressWarnings("unchecked")public List getPeople() {return (List)this.people.clone();} ...
}

这里的做法基本思路是,做一个副本,保证内部引用(这里的people)不会传播到外面。但在实际编写代码的时候,大多数人都不会这么做,能否意识到这样的问题只是一个方面,这样的代码写起来,也要比原来的那种写法麻烦得多。按照许多公司的做法,这种要求只能放到代码规范里,但无论如何,在程序世界里,人为规定永远是最容易忽略的约定。

不过,在真实世界中,即便是我们写的只是上面的最简单那种形式,却很少出现问题。原因何在呢?因为大多数情况下,我们编写这样程序的时候,会有一种隐形的约定,这个“List”是不变的。我们设置(set)完这个List之后,基本上不会留着它的引用在做任何操作;而得到(get)它之后,也基本上不会去修改它。

在这种情况下,我们使用的实际上是一个不变的List。既然是一个不变的List,那不如就更直接地把它表现出来。

Guava为我们提供了不变集合的概念,对应着各种具体类型,有ImmutableList、ImmutableSet,还有ImmutableMap。从名字上,我们不难看出它们的用法。

Guava不变集合的做法并不是另起炉灶,而是遵循了Java已有集合框架的约定。比如,通过查阅文档,我们不难发现,ImmutableList就是一个List,只不过使用这个“List”,只不过,当我们尝试调用诸如add、set之类试图修改集合的方法时,它会抛出异常。正是有了这样的基础,不变集合可以和很多已有的类库、框架配合在一起。

有了这个基础,我们把不变集合的概念应用于之前的代码,它就是下面这个样子:

public class People {private ImmutableList people;public void setPeople(ImmutableList people) {this.people = people;}public ImmutableList getPeople() {return this.people;} ...
}

这样一来,代码依然很简单,但是,意义却与从前完全不一样了。我们不必再为可能存在的隐忧顾虑了:一旦元素放到集合里,就不可能修改它了,因为它是不可变的。

对于使用这段代码的人来说,getter自不必说,如往常一样使用,setter也不费力。只是当做字面量使用的集合,我们已经在《你应该更新的Java知识之集合初始化》中讨论过了。如果要适配于现有程序库,把一个已有的List转成ImmutableList也不复杂,一个简单的copyOf方法就可以实现:

  List existingPeople = ... ImmutableList immutablePeople = copyOf(existingPeople);

为了让讨论更完整,这里不得不提到另外一个不变接口的选择:Iterable。它是从Java 5开始进入JDK的一个接口:

public interface Iterable  {Iterator iterator();
}

作为一个Java程序员,我们对Iterator简直再熟悉不过了,有了Iterator,我们就可以遍历一个集合。所以,在一些情况下,我们也可以使用Iterable表示一个不变集合。大多数Java已有的集合类都实现了这个接口。

既然它是JDK里的东西,为什么不把它优先推荐呢?原因有几个。最重要的一个原因在于我们熟知的Iterator,它有一个方法叫做remove,可能大多数Java程序员已经习惯性地忽略了这个方法,但它就在哪里,它是一个可以“改变”集合的方法,所以,从语义上说,它不是一个很好的选择。另外,从已有的代码习惯来说,很多程序员还是很喜欢用List、Set作为接口,所以,ImmutableList从心理上来说,更接近已有的习惯。剩下的一个点似乎不那么重要,有些代码真的需要使用到特定类型的接口。不过,就大多数代码而言,我们只是要得到的一个集合,做一些操作,而这些操作我们在《你应该更新的Java知识之集合操作》中做了一些讨论。

在函数式编程中,不变是提升程序稳定性一个很重要的概念。既然我们大多数情况下实际用到的是不变集合,那就不妨直接把它表现出来。

你应该更新的Java知识相关推荐

  1. 你应该更新的Java知识之常用程序库

    些库有的解决了平时常见又重要的问题,有的则让Coding变得更惬意,值得全速跟进了解! 原文 在很多人眼中,Java已经是一门垂垂老矣的语言,但并不妨碍Java世界依然在前进.如果你曾离开Java,云 ...

  2. java 声明一个bus类_第11章 新特性 – 你应该更新的Java知识之Observer - Java 基础入门笔记...

    作为一个Java程序员,不熟悉设计模式简直不好意思和人打招呼,而Observer模式可以说是位列最常用的设计模式之列,虽然有时候在具体代码里,它不一定叫这个名字,比如改头换面叫个Listener,但模 ...

  3. 8张图带你轻松温习Java知识

    转载自 8张图带你轻松温习Java知识 1 字符串不变性 下面这张图展示了这段代码做了什么 [code ]String s = "abcd";  s = s.concat(&quo ...

  4. 最全面的Java面试题-----是你更好的掌握java知识

    最全面的Java面试题-----是你更好的掌握java知识 目录 l     概念题--- 1 一.        JAVA基础--- 1 1)      面向对象的特征--- 1 2)      什 ...

  5. 001 JAVA知识体系

    JAVA知识体系 j2se 1.Java语言基础 具体包括:1.对象的初始化:2.继承时,对象的初始化过程:3.关于构造方法:4.有关public.private和protected:5.抽象类:6. ...

  6. 【Scala教程】如何在已掌握的Java知识基础上快速上手Scala?【个人学习记录】

    如何在已掌握的Java知识基础上学习Scala 前言 正文开始! 1. 编译运行 2. 声明变量 3. 输出 4. 显式指定变量类型 5. 范围区间 6. 写入文本文件 7. 读取文本文件 8. if ...

  7. 万字 Java 知识地图助你成为 Offer 收割机

    点击关注"码海" 右上角"设为星标"好文章送达比别人快 我相信这些读者或多或少都有一些 Java 基础,但由于看不到全貌,学了一段时间很容易迷失.所以我在寻思着 ...

  8. JAVA知识体系之多线程篇

    目录 1.线程概述 1.1 线程的定义 1.2 多线程的优势 1.2.1 更多的处理器核心 1.2.2 更快的响应时间 1.3 多线程的挑战 1.3.1 上下文切换 1.3.2 死锁 1.3.3 资源 ...

  9. java知识体系-最新总结(2022版)

    目录 Java面试总结 基础知识 Java概述 基础语法 面向对象 集合框架 IO流 网络编程 常用API 常用工具类库 单元测试 异常 日志 工具 IDEA Eclipse & STS Ma ...

最新文章

  1. 对《软件工程》第四章的理解
  2. Monkey基本使用(转载)
  3. 全球及中国铝拉丝润滑剂行业竞争格局及运营前景研究报告2021-2027年
  4. ALV TREE学习笔记
  5. Windows7 Credential Manage
  6. ARM中各始终之间的关系,FCLK HCLK PCLK的关系
  7. wikipedia_教职员工可以通过Wikipedia进行教学吗?
  8. Java逆序列化报错serialVersionUID不同
  9. ZetCode Java 教程
  10. 硬干货!一张图弄清楚在ESXi下如何进行网络抓包
  11. 中国大陆身份证正则表达式(严格验证省份和日期)
  12. Groovy 教程系列(一)-- Groovy 入门
  13. Linux后台运行程序
  14. 关于IDEA下载安装,jpcap与wincap的一些使用方法
  15. win10下安装deepin双系统的坑:安装完成一直黑屏进不去系统
  16. python四叶玫瑰数,任意位数自幂数寻找|Python练习系列[4]
  17. 【spark使用】4. Dataset转换算子使用
  18. Js数组里删除指定的元素(不是指定的位置)
  19. 海淘转运攻略之2017年黑色星期五海淘转运公司对比推荐
  20. Oracle 查询:一小时内、一天内、一周内等

热门文章

  1. 子网掩码和网络ID的快速计算方法
  2. 关于MFC单选框的使用临时记录,稍后编辑
  3. lucene Hello World
  4. Java 基础总结。
  5. CCF - 201509-2 - 日期计算
  6. Zabbix-3.0.3结合Grafana-3.1.0给你想要的绘图
  7. 基于Bootstrap的jQuery开关按钮插件
  8. 对commonMark.js的理解学习
  9. Eclipse配置 Maven 异常处理
  10. 解决ie6、7 margin-bottom 失效问题