在 Collection 接口里:
boolean add(E e);
boolean remove(Object o);//明明 add 都是类型参数呢
boolean contains(Object o);
还有 Map 接口也是:
V setValue(V value);
boolean equals(Object o);
比如 HashMap 里的 EntrySet 内部类,继承了 AbstractSet,要重写实现 contains 和 remove 方法,还得强转形参。
1
brucefu 2020-01-01 14:55:20 +08:00
引入泛型的目的是:在编译期间起到类型检查机制。remove、contains、equals 方法在使用时没必要进行类型检查
|
2
amiwrong123 OP 比如 HashMap 里的 EntrySet 内部类,继承了 AbstractSet,要重写实现 contains 和 remove 方法,还得强转。
<img src="https://s2.ax1x.com/2020/01/01/lGYRmV.png" alt="lGYRmV.png" border="0"> |
3
Cbdy 2020-01-01 15:12:04 +08:00 via Android
Collection 应该是在 1.5 之前就在 JDK 的,那个时候还没有泛型
|
5
liuming 2020-01-01 16:36:07 +08:00
在 StackOverflow 找到了个相关的
https://stackoverflow.com/questions/104799/why-arent-java-collections-remove-methods-generic |
6
xingda920813 2020-01-01 22:09:21 +08:00
remove 的逻辑是看这个 Collection 的 item 和你传入的要删除的对象是不是 equals,而 Object.equals(Object o) 的逻辑完全是用户自定义的,比如一个 Dog 也可能和一个 Cat 是 equals 的。那从一个 Collection<Dog> 里尝试 remove 一个 Cat 就说的通了。
|
7
amiwrong123 OP @xingda920813
但是,既然 remove 里会用到 equals,那么 Dog 类的重写的 equals 肯定会去判断一下`o instanceof Dog`啊,这个通不过就直接返回 false 了啊。也就不能在 Dog 的集合删除 Cat 了啊。 |
8
amiwrong123 OP @brucefu
可是直觉上,总感觉 contains 和 remove 方法也应该检查啊。😂 我看网上还有一种观点,如果类型参数是通配符`? extends Dog`,像 add 这样的函数就无法使用了,但由于 contains 和 remove 方法的形参类型是 Object,所以这两个函数还能继续使用。 |
9
amiwrong123 OP @Cbdy
希望有一个强有力的例子来说服自己😂怎么个没必要法 |
10
amiwrong123 OP @liuming
看了最高答案,这句话 The example given by him is an intersection of a List of Numbers and a List of Longs.比较在意这个例子到底是啥,难道是在那个视频链接,算了,下班了再看。。。 |
11
xingda920813 2020-01-02 10:20:58 +08:00
@amiwrong123 通常来说 Dog 重写的 equals 会判断是不是 instanceOf Dog,但那是工程上的实践。从语言和虚拟机的层面没有任何限制一个 Dog 不能跟一个 Cat 相等。
比如说 Dog.equals(Object o): if (o instanceOf Cat) return true; |
12
xingda920813 2020-01-02 10:24:27 +08:00
@amiwrong123 或者换一个工程中更实际的例子,比如每个 Dog 都有个全局唯一的 id 属性。equals() 只判断 id 是不是相等,id 相同就认为是同一个 Dog,不看其他属性。
那对于一个 Collection<Dog> 我就可以调用 remove((int) 1024) 来删除编号为 1024 的 Dog 了,不需要构造一个 Dog 对象传入 remove。 |
13
liuming 2020-01-02 14:10:20 +08:00
@amiwrong123
大意是有两个 List,list1 装 Long,list2 装各种 Number,那个 intersection 操作是 list1.retainAll(list2),去掉 list1 中不存在于 list2 的元素,Josh Bloch 说这是 reasonable 的操作,但是如果添加了泛型限制,就没法兼容了,所以他们没有把所有方法都改成泛型的 |
14
cruii 2020-01-03 17:19:31 +08:00
JDK 开发者可不管你到底如何用 remove,如何写 equals 和 hashcode。只需要保证在使用时能正确的实现所需要的功能就行。
一个存储了 14 亿个 Person 对象的 List,我要在 2020 年消灭贫困人口,那我定义的贫困人口就是月收入等于 1000 的人。 定义两个类,一个类是 Person,一个类是 Poor,两个类都只有 2 个字段,String name 和 int salary。 Person 类的 equals 和 hashCode 内容为 @Override public boolean equals(Object obj) { Poor p = (Poor) obj; return this.getMoney() == p.getMoney(); } @Override public int hashCode() { return Objects.hash(this.getMoney()); } Poor 类的 equals 和 hashCode 内容为 @Override public boolean equals(Object obj) { Person p = (Person) obj; return this.getMoney() == p.getMoney(); } @Override public int hashCode() { return Objects.hash(this.getMoney()); } 准备消灭贫困人口 先创建一个容纳 14 亿个 Person 对象的 List List<Person> people = new ArrayList<>(.....); people.add(..); ..... ..... 再创建一个贫困人口对象来代表我定义的贫困人口 Poor poor = new Poor("cruii", 1000); // 就是我为例子了 现在开始消灭 while (people.contains(poor)) { people.remove(poor); } 好了,全部跟我一样贫困的全被消灭了 |