ArrayList和HashSet的Contains()方法(转)
来源: ArrayList和HashSet的Contains()方法
笔试题:
package com.champion.test.exam;
import java.util.ArrayList;
import java.util.HashSet;
public class Foo {
int value;
Foo(int value) {
this.value = value;
}
public boolean equals(Object obj) {
if (obj instanceof Foo) {
Foo foo = (Foo) obj;
return value == foo.value;
} else {
return false;
}
}
/**
* public int hashCode() {
*
* return this.value;
*
* }
*
*/
public static void main(String... args) {
ArrayList list = new ArrayList();
HashSet set = new HashSet();
Foo f1 = new Foo(1);
Foo f2 = new Foo(1);
list.add(f1);
set.add(f2);
Foo f3 = new Foo(1);
Foo f4 = new Foo(1);
System.out.println(list.contains(f3) + "," + set.contains(f4));
}
}
答案:true,false 打开注释后,结果为:true ,true
主要原因为:
ArrayList和HashSet 的contains的 底层的实现不同
ArrayList的contains
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;//如果o为空且集合中i位置处也为空,返回i
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;//如果o不为空,且集合中i位置对象equals对象o,返回i
}
return -1;//否则返回-1
}
所以,因为list中有对象f1,而f1.equals(f3)为true,所以执行indexOf()方法返回0,执行contains()返回true;
HashSet中contains()
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
由于Foo类中重写了equals()而没有重写hashCode()方法,所以会执行父类Object 中的 hashCode 方法,(会针对不同的对象返回不同的整数,具体是将该对象的内部地址转换成一个整数来实现的),由于f2和f4内存地址不同,所以hashcode也不同,所以执行getEntry()方法返回null,执行containsKey返回false,当然的执行contains()也会返回false;
综上所述:对于一个类重写了equals()方法后,重写它的hashCode()方法是必要的,以维护 hashCode 方法的常规协定:相同的对象必须具有相等的哈希码。
ArrayList和HashSet的Contains()方法(转)的更多相关文章
- 【Java必修课】ArrayList与HashSet的contains方法性能比较(JMH性能测试)
1 简介 在日常开发中,ArrayList和HashSet都是Java中很常用的集合类. ArrayList是List接口最常用的实现类: HashSet则是保存唯一元素Set的实现. 本文主要对两者 ...
- Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题
Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...
- Java中如何克隆集合——ArrayList和HashSet深拷贝
编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...
- 【转】Java如何克隆集合——深度拷贝ArrayList和HashSet
原文网址:http://blog.csdn.net/cool_sti/article/details/21658521 原英文链接:http://javarevisited.blogspot.hk/2 ...
- 浅谈Java语言中ArrayList和HashSet的区别
Java语言中ArrayList和HashSet的区别 2019-04-10 13:22:49 一.基本区别 首先一起看个实例,其代码如下: package com.MrZ_baby.com; i ...
- 用HashSet的add方法谈hashcode和equals方法重写
本文主要通过用HashSet的add方法讲一下hashCode和equals方法重写.错误的地方望指正. 1.了解HashSet的add方法 了解一个方法的好办法是看源码,所以先看源码 private ...
- java中把list列表转为arrayList以及arraylist数组截取的简单方法
java中把list列表转为arrayList以及arraylist数组截取的简单方法 package xiaobai; import java.util.ArrayList; import java ...
- Java学习笔记27(集合框架一:ArrayList回顾、Collection接口方法)
集合:集合是java中提供的一种容器,可以用来存储多个数据 集合和数组的区别: 1.数组的长度是固定的,集合的长度是可变的 2.集合中存储的元素必须是引用类型数据 对ArrayList集合的回顾 示例 ...
- ArrayList的add(E e)方法与扩容
ArrayList是Java开发中经常用到的集合类,它是List接口的实现类,具有很高的查询性能,但不是线程安全的.本文主要讲述了ArrayList的add(E e)方法及该方法中涉及到的容量扩容技术 ...
随机推荐
- 21-Python-Django进阶补充篇
1. 路由部分补充 1.1 默认值 url: url(r'^index/', views.index, {'name': 'root'}), views: def index(request,name ...
- [LeetCode] Convert Sorted List to Binary Search Tree 将有序链表转为二叉搜索树
Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...
- 谈一下如何设计Oracle 分区表
在谈设计Oracle分区表之间先区分一下分区表和表空间的个概念: 表空间:表空间是一个或多个数据文件的集合,所有数据对象都存放在指定的表空间中,但主要存放表,故称表空间. 分区表:分区致力于解决支持极 ...
- 关于EventSource的精华
他是keep-alive的连接,服务端持续向这个请求的Reponse发送数据,以"data: "+您的消息+"\n\n"的格式发送,浏览器端会收到您发送的消息. ...
- .Net4.0以上使用System.Data.Sqlite
最近对Sqlite感兴趣,就尝试了一下用c#连接,我用的版本是vs2013,默认开发环境是.net4.5,,按照网上的教材,下载了System.Data.Sqlite,然后写了下面这个简单的测试代码, ...
- C++知识回顾(一)
感觉世界都是约定好的,每门语言的第一个程序总是Hello World!但是也有一些书似乎是在追求个性,会用一些其他的,但是是Not Hello World!本人需要再学习一下C++,所以从最基础的开始 ...
- php设计模式--面向对象
php链式操作的实现: 特点:1.链式操作一般存在于面向对象的情况下链式操作才有意义 /* * SQL语句组合实例类,始发文章web开发笔记 * 学习用,非专业类 * */ class sql{ pr ...
- java script 基础知识
方法:提供信息 函数去处理 给出一个结果 字符类型. 字符提前赋类型 int i=1; money x; float;datetime; decimal;var 万用类型 var a = 1; 1赋值 ...
- 【编码】_C#中编码名称(Name)与页面标识(CodePage)的关系_编码gb2312的获取
在写C#代码时,发现VS提供没有直接提供gb2312的中文编码, 所以,需要找到对应编码名称的codepage来调用想要的编码方式. 下面是微软编程提供的所有编码信息,包括编码名称,编码代码页标识符, ...
- struts2.5的配置及其注意事项
坑爹的apache,官方的jar包提供了一个struts2的运行最小jar包