JAVA-集合源码摘抄

1. Collection

The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered. The JDK does not provide any direct implementations of this interface: it provides implementations of more specific subinterfaces like Set and List. This interface is typically used to pass collections around and manipulate them where maximum generality is desired.
集合层次结构中的根接口。集合表示一组对象,称为其元素。一些集合允许重复元素,而其他集合不允许。有些是有序的,而其他是无序的。JDK不提供此接口的任何直接实现:它提供更具体的子接口(如Set和List)的实现。通常使用此接口将集合传递并在希望达到最大泛化性的地方对其进行操作。

Bags or multisets (unordered collections that may contain duplicate elements) should implement this interface directly.
包或多重集(可能包含重复元素的无序集合)应直接实现此接口。

All general-purpose Collection implementation classes (which typically implement Collection indirectly through one of its subinterfaces) should provide two “standard” constructors: a void (no arguments) constructor, which creates an empty collection, and a constructor with a single argument of type Collection, which creates a new collection with the same elements as its argument. In effect, the latter constructor allows the user to copy any collection, producing an equivalent collection of the desired implementation type. There is no way to enforce this convention (as interfaces cannot contain constructors) but all of the general-purpose Collection implementations in the Java platform libraries comply.
所有通用的Collection实现类(通常通过其子接口之一间接实现Collection)应提供两个“标准”构造函数:一个void(无参数)构造函数,用于创建一个空集合;一个具有Collection类型的单参数的构造函数,用于创建一个具有与其参数相同元素的新集合。实际上,后一个构造函数允许用户复制任何集合,生成所需实现类型的等效集合。没有办法强制执行这个约定(因为接口不能包含构造函数),但是Java平台库中的所有通用Collection实现都遵守这个约定。

个人理解,实现Collection按规范要有两个构造方法
一个是无参构造,一个是有参构造,用于创建一个完全一样的集合。如下:
new ArrayList<>();
new ArrayList<>(codes);

Certain methods are specified to be optional. If a collection implementation doesn’t implement a particular operation, it should define the corresponding method to throw UnsupportedOperationException. Such methods are marked “optional operation” in method specifications of the collections interfaces.
某些方法被指定为可选的。如果集合实现不实现特定操作,它应该定义相应的方法来抛出UnsupportedOperationException。这些方法在集合接口的方法规范中被标记为“可选操作”。

Some collection implementations have restrictions on the elements that they may contain. For example, some implementations prohibit null elements, and some have restrictions on the types of their elements. Attempting to add an ineligible element throws an unchecked exception, typically NullPointerException or ClassCastException. Attempting to query the presence of an ineligible element may throw an exception, or it may simply return false; some implementations will exhibit the former behavior and some will exhibit the latter. More generally, attempting an operation on an ineligible element whose completion would not result in the insertion of an ineligible element into the collection may throw an exception or it may succeed, at the option of the implementation. Such exceptions are marked as “optional” in the specification for this interface.

一些集合实现对它们可能包含的元素有限制。例如,某些实现禁止空元素,某些实现对其元素的类型有限制。尝试添加不合格的元素会引发未检查的异常,通常是NullPointerException或ClassCastException。尝试查询不合格元素的存在可能会引发异常,或者可能只是返回false;某些实现将展现前者的行为,而某些实现将展现后者的行为。更一般地,尝试对不合格元素执行操作,其完成不会导致不合格元素插入集合中,可能会引发异常,也可能会成功,由实现方决定。此类异常在此接口的规范中被标记为“可选”。

It is up to each collection to determine its own synchronization policy. In the absence of a stronger guarantee by the implementation, undefined behavior may result from the invocation of any method on a collection that is being mutated by another thread; this includes direct invocations, passing the collection to a method that might perform invocations, and using an existing iterator to examine the collection.
由每个集合确定其自己的同步策略。在没有实现提供更强保证的情况下,调用正在被另一个线程修改的集合上的任何方法可能会导致未定义的行为;这包括直接调用、将集合传递给可能执行调用的方法以及使用现有的迭代器来检查集合。

Many methods in Collections Framework interfaces are defined in terms of the equals method. For example, the specification for the contains(Object o) method says: “returns true if and only if this collection contains at least one element e such that (onull ? enull : o.equals(e)).” This specification should not be construed to imply that invoking Collection.contains with a non-null argument o will cause o.equals(e) to be invoked for any element e. Implementations are free to implement optimizations whereby the equals invocation is avoided, for example, by first comparing the hash codes of the two elements. (The Object.hashCode() specification guarantees that two objects with unequal hash codes cannot be equal.) More generally, implementations of the various Collections Framework interfaces are free to take advantage of the specified behavior of underlying Object methods wherever the implementor deems it appropriate.
Some collection operations which perform recursive traversal of the collection may fail with an exception for self-referential instances where the collection directly or indirectly contains itself. This includes the clone(), equals(), hashCode() and toString() methods. Implementations may optionally handle the self-referential scenario, however most current implementations do not do so.
Collections Framework接口中的许多方法都是根据equals方法定义的。例如,contains(Object o)方法的规范说:“如果且仅如果此集合包含至少一个元素e,使得(o==null ? e==null : o.equals(e)),则返回true。不能将此规范解释为调用Collection.contains时使用非空参数o将导致为任何元素e调用o.equals(e)。实现可以自由地实现优化,从而避免调用equals,例如,首先比较两个元素的哈希码。(Object.hashCode()规范保证具有不相等哈希码的两个对象不能相等。) 更一般地说,各种集合框架接口的实现可以自由利用底层对象方法的指定行为,无论实现者在何处认为适当。一些对集合进行递归遍历的集合操作可能会对自引用实例失败,即集合直接或间接包含自身的情况下可能会引发异常。这包括了clone()、equals()、hashCode()和toString()方法。实现可以选择性地处理自引用的情况,但是大多数当前的实现并未这样做。

Most collections manage storage for elements they contain. By contrast, view collections themselves do not store elements, but instead they rely on a backing collection to store the actual elements. Operations that are not handled by the view collection itself are delegated to the backing collection. Examples of view collections include the wrapper collections returned by methods such as Collections.checkedCollection, Collections.synchronizedCollection, and Collections.unmodifiableCollection. Other examples of view collections include collections that provide a different representation of the same elements, for example, as provided by List.subList, NavigableSet.subSet, or Map.entrySet. Any changes made to the backing collection are visible in the view collection. Correspondingly, any changes made to the view collection — if changes are permitted — are written through to the backing collection. Although they technically aren’t collections, instances of Iterator and ListIterator can also allow modifications to be written through to the backing collection, and in some cases, modifications to the backing collection will be visible to the Iterator during iteration.
大多数集合管理它们所包含元素的存储。相比之下,视图集合本身不存储元素,而是依赖于支持集合来存储实际的元素。视图集合本身无法处理的操作将被委托给支持集合。视图集合的示例包括由诸如Collections.checkedCollection、Collections.synchronizedCollection和Collections.unmodifiableCollection等方法返回的包装集合。其他视图集合的示例包括提供相同元素的不同表示的集合,例如,由List.subList、NavigableSet.subSet或Map.entrySet提供的表示。对支持集合进行的任何更改都将在视图集合中可见。相应地,对视图集合进行的任何更改(如果允许更改)都将写入支持集合。尽管它们在技术上不是集合,但Iterator和ListIterator的实例也可以允许修改写入到支持集合,而且在某些情况下,对支持集合的修改将在迭代期间对Iterator可见。

2. Map

An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
一个将键映射到值的对象。映射不能包含重复的键;每个键最多只能映射到一个值。

This interface takes the place of the Dictionary class, which was a totally abstract class rather than an interface.
这个接口取代了Dictionary类,Dictionary类是一个完全抽象的类而不是接口。

The Map interface provides three collection views, which allow a map’s contents to be viewed as a set of keys, collection of values, or set of key-value mappings. The order of a map is defined as the order in which the iterators on the map’s collection views return their elements. Some map implementations, like the TreeMap class, make specific guarantees as to their order; others, like the HashMap class, do not.
Map接口提供了三种集合视图,允许将映射的内容视为键集、值集合或键值映射的集合。映射的顺序被定义为迭代器在映射的集合视图上返回它们的元素的顺序。一些映射实现,比如TreeMap类,对它们的顺序做出了具体的保证;而其他的,比如HashMap类,没有做出保证。

Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. A special case of this prohibition is that it is not permissible for a map to contain itself as a key. While it is permissible for a map to contain itself as a value, extreme caution is advised: the equals and hashCode methods are no longer well defined on such a map.
注意:如果可变对象被用作映射的键,则必须格外小心。如果在对象作为映射的键时以影响equals比较的方式改变对象的值,则不指定映射的行为。这种禁止的特例是,映射不得包含自身作为键。虽然允许映射包含自身作为值,但应格外小心:在这种映射上,equals和hashCode方法不再被定义。

上面这段话,举个例子:假设我们有一个Student类表示学生,它有两个属性:id和name。我们将尝试将Student对象用作Map的键。但是,我们要注意,如果我们更改了作为键的Student对象的属性,可能会导致不可预测的结果。

import java.util.*;

class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters and setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // Equals and hashCode methods
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

public class Main {
    public static void main(String[] args) {
        Map<Student, Integer> studentMap = new HashMap<>();

        Student student1 = new Student(1, "Alice");
        studentMap.put(student1, 90);

   		System.out.println("Initial map: " + JSON.toJSONString(studentMap));

       // Now, let's try to modify the key object
        student1.setId(2);

        System.out.println("Modified map: " + JSON.toJSONString(studentMap));
    }
}

Initial map: {{"id":1,"name":"Alice"}:90}
Modified map: {{"id":2,"name":"Alice"}:90}

在这个示例中,我们创建了一个HashMap,将Student对象作为键,成绩作为值。我们首先将一个学生对象student1放入映射中,并打印出初始映射。然后,我们修改了student1的id属性。最后,我们再次打印映射。

运行此代码后,您会发现即使我们没有显式更改映射中的键,但映射的行为仍然受到影响。这是因为Student对象的equals和hashCode方法基于其属性,而我们已经更改了其中一个属性。这导致student1在HashMap中的位置发生了变化,因此我们无法再正确地访问它。这就是在使用可变对象作为映射键时需要格外小心的原因。

其实就是说引用对象被修改了,导致key也改变了,数据在map中的地址也改变了

All general-purpose map implementation classes should provide two “standard” constructors: a void (no arguments) constructor which creates an empty map, and a constructor with a single argument of type Map, which creates a new map with the same key-value mappings as its argument. In effect, the latter constructor allows the user to copy any map, producing an equivalent map of the desired class. There is no way to enforce this recommendation (as interfaces cannot contain constructors) but all of the general-purpose map implementations in the JDK comply.
所有通用映射实现类都应该提供两个“标准”构造函数:一个是void(无参数)构造函数,用于创建一个空映射;另一个是带有Map类型的单个参数的构造函数,用于创建一个具有与其参数相同的键值映射的新映射。实际上,后一个构造函数允许用户复制任何映射,生成所需类的等价映射。虽然没有办法强制执行这个建议(因为接口不能包含构造函数),但JDK中的所有通用映射实现都遵守这个建议。

The “destructive” methods contained in this interface, that is, the methods that modify the map on which they operate, are specified to throw UnsupportedOperationException if this map does not support the operation. If this is the case, these methods may, but are not required to, throw an UnsupportedOperationException if the invocation would have no effect on the map. For example, invoking the putAll(Map) method on an unmodifiable map may, but is not required to, throw the exception if the map whose mappings are to be “superimposed” is empty.
此接口中包含的“破坏性”方法,即修改其操作的映射的方法,如果该映射不支持该操作,则指定抛出UnsupportedOperationException。如果是这种情况,这些方法可能会,但不是必须的,如果调用对映射没有影响,则抛出UnsupportedOperationException异常。例如,在不可修改的映射上调用putAll(Map)方法可能会抛出异常,如果要“叠加”其映射的映射为空,则可能不会抛出异常。

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值