11.1 优化集合
大部分编程语言语言库会提供至少两种通用类型的容器
- 顺序容器:将对象保存在某个特定位置,用索引来表示
- 关联容器:使用对象本身来确定它在集合中应该保存的位置。

11.2 针对列表的优化考虑
核心Java中,基本上有两种列表,即ArrayList和LinkedList。
11.5 领域对象
领域对象是表示应用程序非常重要的业务概念的代码。例如电商网站的Order订单,OrderItem订单项和DeliverySchedule(交货时间表)。这些类型之间通常会有一定的关系(一个Order有多个与之关联的OrderItem实例)
public class Order {private final long id;private final List<OrderItem> items = new ArrayList<>();private DeliverySchedule schedule;public Order(long id) {this.id = id;}public DeliverySchedule getSchedule() {return schedule;}public void setSchedule(DeliverySchedule schedule) {this.schedule = schedule;}public List<OrderItem> getItems() {return items;}public long getId() {return id;}}public class OrderItem {private final long id;private final String description;private final double price;public OrderItem(long id, String description, double price) {this.id = id;this.description = description;this.price = price;}@Overridepublic String toString() {return "OrderItem{" + "id=" + id + ", description=" +description + ", price=" + price + '}';}}public final class DeliverySchedule {private final LocalDate deliveryDate;private final String address;private final double deliveryCost;private DeliverySchedule(LocalDate deliveryDate, String address,double deliveryCost) {this.deliveryDate = deliveryDate;this.address = address;this.deliveryCost = deliveryCost;}public static DeliverySchedule of(LocalDate deliveryDate, String address,double deliveryCost) {return new DeliverySchedule(deliveryDate, address, deliveryCost);}@Overridepublic String toString() {return "DeliverySchedule{" + "deliveryDate=" + deliveryDate +", address=" + address + ", deliveryCost=" + deliveryCost + '}';}}
领域类型之间存在所有权关系。如下图。然而,领域对象图中节点上的大部分数据项最终是简单的数据类型,如字符串、基本类型和LocalDateTime对象
使用jmap -histo 命令。该命令可以帮助我们快速了解Java堆的状态,同样也能通过VisualVM这样的工具来获得。这些工具有助于诊断领域对象在某些情绪下的内存泄漏。
为了说明原因,需要考虑Java堆的几个基本事实
- 分配的最常见的数据结构包括字符串、字符数组、字节数组和Java集合类型的实例
- 在jmap中,与泄漏相对应的数据将表现为大得反常的数据集
也就是说,我们希望不管是按照内存容量还是实例数目,拍在前面的一般是来自核心JDK的数据结构,如果在jmap生成的前30个左右的条目出现了特定于应用程序的领域对象,那就是内存泄漏的迹象。
领域对象发生泄漏的另一个常见行为是对“所有代”的影响。之所以出现这种影响,是因为特定类型的对象在应该回收的时候没有被回收,从而导致它们最终会存活足够长的时间而进入Tenured区,在熬过足够多的手机周期后,它们的代极端可能会表现为各种可能的值。
