Java简明笔记(十) 输入与输出

文本输入和输出

文本输入

对于较短的文本,我们可以直接把文本存到一个String里

1
2
3
4
5
// 整个文本
String contents = new String(readAllBytes((Paths.get("alice.txt"))), StandardCharsets.UTF_8);

// 以非字母为分隔符,变成一个个单词
List<String> words = Arrays.asList(contents.split("\\PL+"));

如果想按行读取,可以读文件并存到 List 集合里,集合的每一个元素代表每一行的一个String

1
2
// 按行读取
List<String> lines = Files.readAllLines(path, charset);
阅读更多

Java简明笔记(九)Stream API

Stream

Java 中的 Stream 提供了数据源,让你可以在比集合类更高的概念层上指定操作。使用 Stream,只需要指定做什么,而不是怎么做。你只需要将操作的调度执行留给实现。

简单地说,流就是一组数据,经过某种操作,产生我们所需的新流,或者输出成非流数据。

流的来源,可以是集合,数组,I/O channel, 生成器(generator)等。流的聚合操作类似 SQL 语句,比如filter, map, reduce, find, match, sorted等。

例如,从文件从获取流:

1
2
3
try (Stream<String> lines = Files.lines(Paths.get("/path/to/file.txt"))) {
...
}
阅读更多

Java简明笔记(八)Lambda和函数式编程

函数式编程

我们平时所采用的 命令式编程(OO也是命令式编程的一种)关心解决问题的步骤。你要做什么事情,你得把达到目的的步骤详细的描述出来,然后交给机器去运行。

而函数式编程关心数据的映射,或者说,关心类型(代数结构)之间的关系。这里的映射就是数学上“函数”的概念,即一种东西和另一种东西之间的对应关系。所以,函数式编程的“函数”,是数学上的“函数”(映射),而不是编程语言中的函数或方法

函数式编程的思维就是如何将这个关系组合起来,用数学的构造主义将其构造出你设计的程序。用计算来表示程序,用计算的组合来表达程序的组合。

阅读更多

Java简明笔记(七) 异常和断言

异常处理

在Java异常处理中,一个方法可以通过 抛出(throw) 异常来发出一个严重问题的信号。调用链中的某个方法,负责 捕获(catch) 并处理异常。捕获到的异常不仅可以在当前方法中处理,还可以将异常抛给调用它的上一级方法去处理。

异常处理的根本优点是:将错误检测和错误处理的过程解耦。

Java 的异常都派生自 Throwable 类,Throwable 又分为 Error 和 Exception。Error 不是我们的程序所能够处理的,比如系统内存耗尽。我们能预知并处理的错误属于 Exception。Exception又分为 unchecked exception 和 checked exception。 unchecked exception 属于 RuntimeException 。

当然,所有的异常都发生在运行时(Runtime),但是 RuntimeException 派生的子类异常在编译时不会被检查。

阅读更多

Java中的 String

String 的本质

在 Java8 中,分析 java.lang.String 类的源码,可以发现 String 内部维护的是一个 char 数组。同时可以发现,String类被 final 修饰,即不可变的。

1
2
3
4
5
6
7
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];

//...
}

在 Java9 中,将 char 数组优化成了 byte 数组。

1
private final byte value[];
阅读更多

Java简明笔记(六) 集合

集合和集合框架

什么是集合?

集合就是一个放数据的容器,准确的说是放数据对象引用的容器。

Java集合主要可以划分为三个部分:

  1. Collection(包含 List 和 Set )
  2. Map (键值对)
  3. 工具类(Iterator迭代器、Enumeration枚举类、Arrays和VCollections)
阅读更多

Java简明笔记(五) 泛型编程

什么是泛型类

假设我们现在有一个存储字符串字典键值对的类,就像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Entry {
private int key;
private String value;

// 构造函数:int 类型的 key, String 类型的 value
public Entry(int key, String value) {
this.key = key;
this.value = value;
}

public int getKey() { return key; }
public String getValue() { return value; }
}

在这个类中,我们用 int 类型来存储 key 值, 用 String 类型来存储 value 值。

现在,老板要求,除了 int 类型的 key 和 String 类型的 value之外,还得提供其他类型的 key 和 value 。 比如 double 类型的 key, boolean 类型的value。

我们不可能写很多个相似的类,只是换一下类型。8种基本数据类型或许可以这么干,但是存储的是抽象数据类型呢?我们不可能所有类型都写一个对应的类。

为了解决这个问题,我们可以用 Java 泛型: 只写一个类,实例化的时候再写明是什么类型就好了。这就是泛型类。

泛型仅仅是java的语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码。

阅读更多

Java简明笔记(四) 继承

什么是继承

继承是在现有的类的基础上创建新类的过程。继承一个类,你也就重用了它的方法,而且还可以添加新的方法和域。

举个例子:员工有薪水,管理者有薪水+奖金, 管理者继承员工,增加 bounus 字段和 setBonus 方法即可。这种情况就是管理者类继承了员工类。

1
2
3
4
5
6
7
8
public class Manager extends Employee {
private double bonus;
...

public void setBonus (double bouns) {
this.bonus = bonus;
}
}

Manager类继承了Employee类,除了获得Employee类的变量和方法外,还额外添加了bonus变量和setBonus方法。

阅读更多

Java简明笔记(三) 接口

什么是接口

假设有一种整数序列服务,这种服务可以计算前n个整数的平均值。就像这样:

1
2
3
4
5
public static double average(IntSequence seq, int n){
...
return average
}

我们传入一个序列seq,以及我们想计算这个序列的前n个数,它返回平均数。

然而,这样的序列可以有很多种形式,比如用户给出的序列、随机数序列、素数序列、整数数组中的元素序列……

阅读更多