Java 中文官方教程 2022 版(二十七)(4)

简介: Java 中文官方教程 2022 版(二十七)

Java 中文官方教程 2022 版(二十七)(3)https://developer.aliyun.com/article/1486852

不可变单例集合

有时你会需要一个不可变的单例Set,它由一个指定的元素组成。Collections.singleton方法返回这样一个Set。这种实现的一个用途是从Collection中删除所有指定元素的出现。

c.removeAll(Collections.singleton(e));

一个相关的惯用法是从Map中删除映射到指定值的所有元素。例如,假设你有一个将人员映射到他们的工作领域的Mapjob — 并且假设你想要消除所有律师。下面的一行代码就能完成任务。

job.values().removeAll(Collections.singleton(LAWYER));

这种实现的另一个用途是为一个写成接受值集合的方法提供单个输入值。

空 Set、List 和 Map 常量

Collections 类提供了返回空SetListMap的方法 — emptySetemptyListemptyMap。这些常量的主要用途是作为不提供任何值时作为值的集合的输入方法的输入,就像这个例子中一样。

tourist.declarePurchases(Collections.emptySet());

实现摘要

原文:docs.oracle.com/javase/tutorial/collections/implementations/summary.html

实现是用于存储集合的数据对象,这些对象实现了接口课程中描述的接口。

Java 集合框架提供了几个核心接口的通用实现:

  • 对于Set接口,HashSet是最常用的实现。
  • 对于List接口,ArrayList是最常用的实现。
  • 对于Map接口,HashMap是最常用的实现。
  • 对于Queue接口,LinkedList是最常用的实现。
  • 对于Deque接口,ArrayDeque是最常用的实现。

每个通用实现提供其接口中包含的所有可选操作。

Java 集合框架还提供了几个特殊用途的实现,用于需要非标准性能、使用限制或其他异常行为的情况。

java.util.concurrent包含几个集合实现,这些实现是线程安全的,但不受单个排他锁的控制。

Collections类(与Collection接口相对),提供了在集合上操作或返回集合的静态方法,这些方法被称为包装器实现。

最后,还有几个便利实现,当您不需要它们的全部功能时,这些便利实现可能比通用实现更有效。这些便利实现通过静态工厂方法提供。

问题和练习:实现方式

原文:docs.oracle.com/javase/tutorial/collections/implementations/QandE/questions.html

问题

  1. 你计划编写一个程序,使用几个基本的集合接口:SetListQueueMap。你不确定哪种实现方式最适合,所以决定在了解程序在实际环境中如何运行之前,先使用通用的实现方式。这些实现方式是哪些?
  2. 如果你需要一个提供按值排序迭代的Set实现,应该使用哪个类?
  3. 你使用哪个类来访问包装器实现?

练习

  1. 编写一个程序,将由第一个命令行参数指定的文本文件读入一个List中。然后,程序应该打印文件中的随机行,打印的行数由第二个命令行参数指定。编写程序时,应一次性分配正确大小的集合,而不是在读取文件时逐渐扩展。提示:要确定文件中的行数,可以使用java.io.File.length来获取文件的大小,然后除以平均行的假定大小。

检查你的答案。

教训:算法

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

这里描述的多态算法是 Java 平台提供的可重用功能块。所有这些功能块都来自Collections类,并且都采用静态方法的形式,其第一个参数是要执行操作的集合。Java 平台提供的绝大多数算法都是在List实例上操作的,但其中有一些是在任意Collection实例上操作的。本节简要描述了以下算法:

  • 排序
  • 洗牌
  • 常规数据操作
  • 搜索
  • 组合
  • 查找极值

排序

sort算法重新排列一个List,使其元素按照一种排序关系升序排列。提供了两种形式的操作。简单形式接受一个List,并根据其元素的自然排序对其进行排序。如果您对自然排序的概念不熟悉,请阅读对象排序部分。

sort操作使用了一个稍微优化的归并排序算法,速度快且稳定:

  • 快速:它保证在n log(n)时间内运行,并在几乎排序好的列表上运行得更快。经验测试表明它与高度优化的快速排序一样快。快速排序通常被认为比归并排序更快,但不稳定且不能保证n log(n)性能。
  • 稳定:它不会重新排序相等的元素。这一点对于在不同属性上重复对同一列表进行排序很重要。如果邮件程序的用户按邮件日期对收件箱进行排序,然后按发件人对其进行排序,用户自然期望来自同一发件人的现在连续的邮件列表仍然按邮件日期排序。只有第二次排序是稳定的才能保证这一点。

以下简单程序按字典顺序打印出其参数。

import java.util.*;
public class Sort {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(args);
        Collections.sort(list);
        System.out.println(list);
    }
}

让我们运行程序。

% java Sort i walk the line

产生了以下输出。

[i, line, the, walk]

该程序仅用于向您展示算法确实像看起来那样易于使用。

第二种sort形式除了List之外还需要一个Comparator,并使用Comparator对元素进行排序。假设你想要按照我们之前示例中的字谜分组的大小倒序打印出来,即最大的字谜组首先显示。接下来的示例展示了如何借助sort方法的第二种形式实现这一目标。

请记住,变位词组以List实例的形式存储在Map中的值中。修改后的打印代码通过Map的值视图迭代,将通过最小大小测试的每个List放入一个ListList中。然后,该代码对此List进行排序,使用一个期望List实例的Comparator,并实现逆大小排序。最后,该代码对排序后的List进行迭代,打印其元素(变位词组)。以下代码替换了Anagrams示例中main方法末尾的打印代码。

// Make a List of all anagram groups above size threshold.
List<List<String>> winners = new ArrayList<List<String>>();
for (List<String> l : m.values())
    if (l.size() >= minGroupSize)
        winners.add(l);
// Sort anagram groups according to size
Collections.sort(winners, new Comparator<List<String>>() {
    public int compare(List<String> o1, List<String> o2) {
        return o2.size() - o1.size();
    }});
// Print anagram groups.
for (List<String> l : winners)
    System.out.println(l.size() + ": " + l);

在与 The Map Interface 部分相同的字典上运行程序,具有相同的最小变位词组大小(八),产生以下输出。

12: [apers, apres, asper, pares, parse, pears, prase,
       presa, rapes, reaps, spare, spear]
11: [alerts, alters, artels, estral, laster, ratels,
       salter, slater, staler, stelar, talers]
10: [least, setal, slate, stale, steal, stela, taels,
       tales, teals, tesla]
9: [estrin, inerts, insert, inters, niters, nitres,
       sinter, triens, trines]
9: [capers, crapes, escarp, pacers, parsec, recaps,
       scrape, secpar, spacer]
9: [palest, palets, pastel, petals, plates, pleats,
       septal, staple, tepals]
9: [anestri, antsier, nastier, ratines, retains, retinas,
       retsina, stainer, stearin]
8: [lapse, leaps, pales, peals, pleas, salep, sepal, spale]
8: [aspers, parses, passer, prases, repass, spares,
       sparse, spears]
8: [enters, nester, renest, rentes, resent, tenser,
       ternes,��treens]
8: [arles, earls, lares, laser, lears, rales, reals, seral]
8: [earings, erasing, gainers, reagins, regains, reginas,
       searing, seringa]
8: [peris, piers, pries, prise, ripes, speir, spier, spire]
8: [ates, east, eats, etas, sate, seat, seta, teas]
8: [carets, cartes, caster, caters, crates, reacts,
       recast,��traces]

洗牌

shuffle算法与sort的作用相反,破坏了List中可能存在的任何顺序痕迹。换句话说,该算法根据来自随机源的输入重新排序List,以使所有可能的排列以相等的概率发生,假设有一个公平的随机源。该算法在实现游戏机会时非常有用。例如,它可以用来洗牌代表一副牌的Card对象的List。此外,它还用于生成测试用例。

此操作有两种形式:一种接受一个List并使用默认的随机源,另一种要求调用者提供一个Random对象作为随机源。该算法的代码被用作List部分的示例。

常规数据操作

Collections类提供了五种用于在List对象上进行常规数据操作的算法,所有这些算法都非常简单:

  • reverse — 颠倒List中元素的顺序。
  • fill — 用指定值覆盖List中的每个元素。此操作对重新初始化List非常有用。
  • copy — 接受两个参数,目标List和源List,并将源的元素复制到目标中,覆盖其内容。目标List的长度必须至少与源相同。如果目标更长,则目标中剩余的元素不受影响。
  • swap — 交换List中指定位置的元素。
  • addAll — 将所有指定的元素添加到Collection中。要添加的元素可以逐个指定,也可以作为数组指定。

搜索

binarySearch算法在排序的List中搜索指定的元素。该算法有两种形式。第一种接受一个List和一个要搜索的元素(“搜索键”)。这种形式假定List根据其元素的自然顺序按升序排序。第二种形式除了List和搜索键外还接受一个Comparator,并假定List根据指定的Comparator按升序排序。在调用binarySearch之前,可以使用sort算法对List进行排序。

两种形式的返回值相同。如果List包含搜索键,则返回其索引。如果没有,则返回值为(-(插入点) - 1),其中插入点是将值插入List的位置,或者大于该值的第一个元素的索引,或者list.size()如果List中的所有元素都小于指定值。这个确实丑陋的公式保证了返回值仅当找到搜索键时为>= 0。这基本上是一个将布尔值(found)和整数值(index)组合成单个int返回值的技巧。

下面的习语可用于binarySearch操作的两种形式,查找指定的搜索键,并在适当位置插入它(如果尚未存在)。

int pos = Collections.binarySearch(list, key);
if (pos < 0)
   l.add(-pos-1, key);

组成

频率和不相交算法测试一个或多个Collections的组成方面:

  • frequency — 计算指定元素在指定集合中出现的次数
  • disjoint — 确定两个Collections是否不相交;即它们是否没有共同元素。

查找极值

minmax算法分别返回指定Collection中包含的最小和最大元素。这两个操作有两种形式。简单形式只接受一个Collection,根据元素的自然顺序返回最小(或最大)元素。第二种形式除了Collection外还接受一个Comparator,根据指定的Comparator返回最小(或最大)元素。

教训:自定义集合实现

原文:docs.oracle.com/javase/tutorial/collections/custom-implementations/index.html

许多程序员永远不需要实现自己的Collection类。您可以通过使用本章前面描述的实现来走得很远。但是,总有一天您可能想要编写自己的实现。借助 Java 平台提供的抽象实现,这样做相当容易。在讨论如何编写实现之前,让我们讨论一下为什么您可能想要编写一个。

编写实现的原因

以下列表说明了您可能想要实现的自定义Collection类型。这并不是详尽无遗的:

  • 持久性:所有内置的Collection实现都驻留在主内存中,并在程序退出时消失。如果您希望在下次程序启动时仍然存在的集合,可以通过在外部数据库上构建一个薄层来实现它。这样的集合可能可以被多个程序同时访问。
  • 特定应用:这是一个非常广泛的类别。一个例子是包含实时遥测数据的不可修改的Map。键可以表示位置,值可以根据get操作从这些位置的传感器中读取。
  • 高性能,特定用途:许多数据结构利用受限使用来提供比通用实现更好的性能。例如,考虑一个包含长时间相同元素值的List。这样的列表在文本处理中经常出现,可以进行运行长度编码 — 运行可以表示为包含重复元素和连续重复次数的单个对象。这个例子很有趣,因为它在性能方面进行了权衡:它需要更少的空间但比ArrayList需要更多的时间。
  • 高性能,通用用途:Java 集合框架的设计者试图为每个接口提供最佳的通用实现,但是可以使用许多许多数据结构,并且每天都会有新的数据结构被发明。也许您可以想出更快的解决方案!
  • 增强功能:假设您需要一个高效的包实现(也称为multiset):一个Collection,它在允许重复元素的同时提供常数时间的包含性检查。在HashMap之上实现这样一个集合是相当简单的。
  • 便利性:您可能希望提供超出 Java 平台提供的便利的其他实现。例如,您可能经常需要表示一系列Integer的连续范围的List实例。
  • 适配器:假设您正在使用具有自己的特定集合 API 的旧 API。您可以编写一个适配器实现,使这些集合能够在 Java 集合框架中运行。适配器实现是一个薄膜,包装一种类型的对象,并通过将对后者类型的操作转换为对前者类型的操作来使其行为类似于另一种类型的对象。

如何编写自定义实现

编写自定义实现出人意料地容易。Java 集合框架提供了专门设计用于促进自定义实现的抽象实现。我们将从以下Arrays.asList实现的示例开始。

public static <T> List<T> asList(T[] a) {
    return new MyArrayList<T>(a);
}
private static class MyArrayList<T> extends AbstractList<T> {
    private final T[] a;
    MyArrayList(T[] array) {
        a = array;
    }
    public T get(int index) {
        return a[index];
    }
    public T set(int index, T element) {
        T oldValue = a[index];
        a[index] = element;
        return oldValue;
    }
    public int size() {
        return a.length;
    }
}

信不信由你,这与包含在java.util.Arrays中的实现非常接近。就是这么简单!您提供一个构造函数和getsetsize方法,AbstractList会处理其余的所有事情。您将获得ListIterator,批量操作,搜索操作,哈希码计算,比较和字符串表示。

假设您想让实现变得更快一点。抽象实现的 API 文档准确描述了每个方法的实现方式,因此您将知道要重写哪些方法以获得所需的性能。前面的实现性能很好,但可以稍微改进一下。特别是,toArray方法会遍历List,一次复制一个元素。鉴于内部表示,仅克隆数组会更快更合理。

public Object[] toArray() {
    return (Object[]) a.clone();
}

添加此覆盖和其他几个类似的覆盖后,此实现与java.util.Arrays中找到的实现完全相同。为了充分披露,使用其他抽象实现会有点困难,因为您将不得不编写自己的迭代器,但仍然不是那么困难。

以下列表总结了抽象实现:

  • AbstractCollection — 既不是Set也不是ListCollection。至少,您必须提供iteratorsize方法。
  • AbstractSet — 一个Set;使用方式与AbstractCollection相同。
  • AbstractList — 由随机访问数据存储支持的List。至少,您必须提供位置访问方法(get,可选的setremoveadd)以及size方法。抽象类负责listIterator(和iterator)。
  • AbstractSequentialList — 由顺序访问数据存储支持的List,例如链表。至少,你必须提供listIteratorsize方法。抽象类负责处理位置访问方法。(这与AbstractList相反。)
  • AbstractQueue — 至少,你必须提供offerpeekpollsize方法以及支持removeiterator
  • AbstractMap — 一个Map。至少你必须提供entrySet视图。通常使用AbstractSet类来实现。如果Map是可修改的,你还必须提供put方法。

编写自定义实现的过程如下:

  1. 从上述列表中选择适当的抽象实现类。
  2. 为类的所有抽象方法提供实现。如果你的自定义集合是可修改的,你还必须重写一个或多个具体方法。抽象实现类的 API 文档将告诉你哪些方法需要重写。
  3. 测试并且,如果需要,调试实现。现在你有一个可工作的自定义集合实现。
  4. 如果你关心性能,阅读抽象实现类的 API 文档,了解你要继承的所有方法的实现。如果有任何方法看起来太慢,就重写它们。如果你重写任何方法,请确保在重写之前和之后测量方法的性能。调整性能的努力程度应该取决于实现的使用程度以及其使用对性能的关键性。 (通常最好省略此步骤。)

课程:互操作性

原文:docs.oracle.com/javase/tutorial/collections/interoperability/index.html

在这一部分,您将学习互操作性的以下两个方面:

  • 兼容性:本小节描述了如何使集合能够与早于将Collection添加到 Java 平台的旧 API 一起工作。
  • API 设计:本小节描述了如何设计新的 API,以便它们能够与其他 API 无缝互操作。

兼容性

原文:docs.oracle.com/javase/tutorial/collections/interoperability/compatibility.html

Java 集合框架旨在确保核心集合接口与早期 Java 平台版本中用于表示集合的类型之间的完全互操作性:VectorHashtable,数组,以及Enumeration。在本节中,您将学习如何将旧集合转换为 Java 集合框架集合,反之亦然。

向上兼容性

假设你正在使用一个返回传统集合的 API 以及另一个 API,需要对象实现集合接口。为了使这两个 API 顺利互操作,你必须将传统集合转换为现代集合。幸运的是,Java 集合框架使这变得容易。

假设旧的 API 返回一个对象数组,而新的 API 需要一个Collection。集合框架有一个方便的实现,允许将对象数组视为List。你可以使用Arrays.asList将数组传递给任何需要CollectionList的方法。

Foo[] result = oldMethod(arg);
newMethod(Arrays.asList(result));

如果旧的 API 返回一个VectorHashtable,你根本不需要做任何工作,因为Vector已经被改装为实现List接口,而Hashtable已经被改装为实现Map。因此,Vector可以直接传递给任何需要CollectionList的方法。

Vector result = oldMethod(arg);
newMethod(result);

类似地,Hashtable可以直接传递给任何需要Map的方法。

Hashtable result = oldMethod(arg);
newMethod(result);

较少情况下,一个 API 可能返回一个代表对象集合的EnumerationCollections.list方法将Enumeration转换为Collection

Enumeration e = oldMethod(arg);
newMethod(Collections.list(e));

向后兼容性

假设你正在使用一个返回现代集合的 API 以及另一个 API,需要你传递传统集合。为了使这两个 API 顺利互操作,你必须将现代集合转换为旧集合。同样,Java 集合框架使这变得容易。

假设新的 API 返回一个Collection,而旧的 API 需要一个Object数组。正如你可能知道的那样,Collection接口包含一个专门设计用于这种情况的toArray方法。

Collection c = newMethod();
oldMethod(c.toArray());

如果旧的 API 需要一个String数组(或其他类型)而不是一个Object数组怎么办?你只需使用toArray的另一种形式 — 需要一个数组作为输入的形式。

Collection c = newMethod();
oldMethod((String[]) c.toArray(new String[0]));

如果旧的 API 需要一个Vector,标准集合构造函数会派上用场。

Collection c = newMethod();
oldMethod(new Vector(c));

需要Hashtable的旧 API 的情况类似处理。

Map m = newMethod();
oldMethod(new Hashtable(m));

最后,如果旧的 API 需要一个Enumeration怎么办?这种情况并不常见,但偶尔会发生,Collections.enumeration 方法就是为了处理这种情况而提供的。这是一个静态工厂方法,接受一个Collection并返回该Collection中元素的Enumeration

Collection c = newMethod();
oldMethod(Collections.enumeration(c));

API 设计

原文:docs.oracle.com/javase/tutorial/collections/interoperability/api-design.html

在这个简短但重要的部分,你将学到一些简单的准则,让你的 API 能够与遵循这些准则的所有其他 API 无缝交互。实质上,这些规则定义了在集合世界中成为一个好“公民”所需的条件。

参数

如果你的 API 包含一个需要在输入时传入集合的方法,那么声明相关参数类型为集合接口类型至关重要。永远不要使用实现类型,因为这违背了基于接口的集合框架的目的,即允许集合在不考虑实现细节的情况下进行操作。

此外,你应该始终使用最不具体的类型。例如,如果Collection足够了,就不要要求一个List或者一个Set。并不是说你在输入时永远不应该要求一个List或者Set;如果一个方法依赖于这些接口的属性,那么这样做是正确的。例如,Java 平台提供的许多算法在输入时需要一个List,因为它们依赖于列表是有序的这一事实。然而,作为一般规则,最好在输入时使用最通用的类型:CollectionMap


注意: 永远不要定义自己的临时collection类,并要求在输入时使用这些类的对象。这样做会使你失去 Java 集合框架提供的所有好处。


返回值

对于返回值,你可以比输入参数更加灵活。可以返回任何实现或扩展集合接口之一的类型的对象。这可以是接口之一,也可以是扩展或实现这些接口的特殊用途类型。

例如,可以想象一个图像处理包,称为ImageList,它返回实现List的新类的对象。除了List操作外,ImageList还可以支持任何看起来有用的特定应用操作。例如,它可能提供一个indexImage操作,返回一个包含ImageList中每个图形缩略图的图像。需要注意的是,即使 API 在输出时提供ImageList实例,它也应该接受任意的Collection(或者也许是List)实例作为输入。

从某种意义上说,返回值应该具有与输入参数相反的行为:最好返回最具体的适用集合接口,而不是最一般的。例如,如果你确定总是返回一个SortedMap,你应该给相关方法返回类型为SortedMap,而不是MapSortedMap 实例比普通的Map实例更耗时构建,也更强大。考虑到你的模块已经投入了时间来构建SortedMap,让用户访问其增强功能是明智的。此外,用户将能够将返回的对象传递给需要SortedMap的方法,以及接受任何Map的方法。

传统 API

目前有很多 API 定义了自己的临时集合类型。虽然这很不幸,但考虑到 Java 平台的前两个主要版本中没有集合框架,这是现实。假设你拥有其中一个这样的 API;以下是你可以采取的措施。

如果可能的话,更新你的传统集合类型以实现标准集合接口之一。然后,你返回的所有集合将与其他基于集合的 API 无缝地进行交互。如果这是不可能的(例如,因为一个或多个现有类型签名与标准集合接口冲突),定义一个适配器类,包装你的传统集合对象之一,使其能够作为标准集合运行。(Adapter 类是自定义实现的一个示例。)

如果可能的话,通过新的调用来更新你的 API,遵循输入指南以接受标准集合接口的对象。这样的调用可以与接受传统集合类型的调用共存。如果这是不可能的,为你的传统类型提供一个构造函数或静态工厂,接受一个标准接口的对象,并返回包含相同元素(或映射)的传统集合。这两种方法中的任何一种都将允许用户将任意集合传递给你的 API。

教程:日期时间

原文:docs.oracle.com/javase/tutorial/datetime/index.html

日期时间包,java.time,在 Java SE 8 发布中引入,提供了一个全面的日期和时间模型,并在JSR 310: 日期和时间 API下开发。虽然java.time基于国际标准化组织(ISO)日历系统,但也支持常用的全球日历。

这个教程涵盖了使用基于 ISO 的类来表示日期和时间以及操作日期和时间值的基础知识。

教训:日期时间概述

原文:docs.oracle.com/javase/tutorial/datetime/overview/index.html

时间似乎是一个简单的主题;即使是一只廉价的手表也可以提供相当准确的日期和时间。然而,仔细观察后,你会意识到时间的微妙复杂性和许多影响你对时间理解的因素。例如,将一个月加到 1 月 31 日的结果对于闰年和其他年份是不同的。时区也增加了复杂性。例如,一个国家可能会在短时间内进入和退出夏令时,或者一年内多次进入和退出夏令时,或者在某一年完全跳过夏令时。

日期时间 API 使用ISO-8601中定义的日历系统作为默认日历。这个日历基于格里高利历系统,在全球范围内被用作代表日期和时间的事实标准。日期时间 API 中的核心类的名称如LocalDateTimeZonedDateTimeOffsetDateTime。所有这些类都使用 ISO 日历系统。如果你想使用另一个日历系统,比如伊斯兰历或泰国佛历,java.time.chrono包允许你使用其中一个预定义的日历系统。或者你也可以创建自己的日历系统。

日期时间 API 使用Unicode 通用区域数据存储库 (CLDR)。这个存储库支持世界上的语言,并包含可用的最大的区域数据集合。这个存储库中的信息已被本地化到数百种语言。日期时间 API 还使用时区数据库 (TZDB)。这个数据库提供自 1970 年以来全球每个时区变更的信息,以及自该概念引入以来主要时区的历史。

日期时间设计原则

原文:docs.oracle.com/javase/tutorial/datetime/overview/design.html

日期时间 API 是根据几个设计原则开发的。

清晰

API 中的方法被明确定义,其行为清晰可预期。例如,使用null参数值调用日期时间方法通常会触发NullPointerException

流畅

日期时间 API 提供了流畅的接口,使代码易于阅读。因为大多数方法不允许带有null值的参数,并且不返回null值,方法调用可以链接在一起,结果代码可以快速理解。例如:

LocalDate today = LocalDate.now();
LocalDate payday = today.with(TemporalAdjusters.lastDayOfMonth()).minusDays(2);

不可变

日期时间 API 中的大多数类创建的对象是不可变的,这意味着在对象创建后,它是不能被修改的。要修改不可变对象的值,必须构建一个修改后的原始副本作为新对象。这也意味着日期时间 API 在定义上是线程安全的。这影响了 API,大多数用于创建日期或时间对象的方法都以offromwith为前缀,而不是构造函数,并且没有set方法。例如:

LocalDate dateOfBirth = LocalDate.of(2012, Month.MAY, 14);
LocalDate firstBirthday = dateOfBirth.plusYears(1);

可扩展

日期时间 API 在尽可能的地方是可扩展的。例如,您可以定义自己的时间调整器和查询,或构建自己的日历系统。

日期时间包

原文:docs.oracle.com/javase/tutorial/datetime/overview/packages.html

日期时间 API 由主要包java.time和四个子包组成:

java.time

该 API 的核心用于表示日期和时间。它包括了日期、时间、日期和时间的组合、时区、瞬间、持续时间和时钟的类。这些类基于 ISO-8601 中定义的日历系统,是不可变的和线程安全的。

java.time.chrono

用于表示除默认 ISO-8601 之外的日历系统的 API。您也可以定义自己的日历系统。本教程不会详细介绍这个包。

java.time.format

用于格式化和解析日期和时间的类。

java.time.temporal

扩展 API,主要用于框架和库的编写者,允许日期和时间类之间的互操作,查询和调整。在这个包中定义了字段(TemporalFieldChronoField)和单位(TemporalUnitChronoUnit)。

java.time.zone

支持时区、时区偏移和时区规则的类。如果涉及时区,大多数开发人员只需要使用ZonedDateTimeZoneIdZoneOffset

相关文章
|
7月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
363 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
3月前
|
Oracle Java 关系型数据库
java 编程基础入门级超级完整版教程详解
这份文档是针对Java编程入门学习者的超级完整版教程,涵盖了从环境搭建到实际项目应用的全方位内容。首先介绍了Java的基本概念与开发环境配置方法,随后深入讲解了基础语法、控制流程、面向对象编程的核心思想,并配以具体代码示例。接着探讨了常用类库与API的应用,如字符串操作、集合框架及文件处理等。最后通过一个学生成绩管理系统的实例,帮助读者将理论知识应用于实践。此外,还提供了进阶学习建议,引导学员逐步掌握更复杂的Java技术。适合初学者系统性学习Java编程。资源地址:[点击访问](https://pan.quark.cn/s/14fcf913bae6)。
306 2
|
8月前
|
消息中间件 Java 数据库
自研Java框架 Sunrays-Framework使用教程「博客之星」
### Sunrays-Framework:助力高效开发的Java微服务框架 **Sunrays-Framework** 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件。它旨在简化数据访问、缓存管理、消息队列、文件存储等常见开发任务,帮助开发者快速构建高质量的企业级应用。 #### 核心功能 - **MyBatis-Plus**:简化数据访问层开发,提供强大的 CRUD 操作和分页功能。 - **Redis**:实现高性能缓存和分布式锁,提升系统响应速度。 - **RabbitMQ**:可靠的消息队列支持,适用于异步
自研Java框架 Sunrays-Framework使用教程「博客之星」
|
9月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
8460 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
8月前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
133 4
|
8月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
145 1
|
9月前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
557 26
|
8月前
|
前端开发 Java 开发工具
Git使用教程-将idea本地Java等文件配置到gitte上【保姆级教程】
本内容详细介绍了使用Git进行版本控制的全过程,涵盖从本地仓库创建到远程仓库配置,以及最终推送代码至远程仓库的步骤。
416 0
|
9月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
9月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)

热门文章

最新文章