本节主要是为了搞懂
1.为什么重写equals方法和hashcode的作用
2.ListIterator的使用
3.Set的不允许重复性的背后
首先新建一个实体类
package utilbag;
public class User {
private String user_id;
private String user_name;
public User(){
}
public User(String user_id,String user_name){
this.user_id=user_id;
this.user_name=user_name;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String toString(){
return "[user_id"+user_id+",user_name="+user_name+"]";
}
//重写了equals方法
public boolean equals(Object obj){
if (this == obj) {
return true;
}
if(obj==null){
return false;
}
if(!(obj instanceof User)){
return false;
}
if(this.user_id==null || this.user_name==null){
return false;
}
User u=(User)obj;
return(this.user_id.equals(u.user_id) && this.user_name.equals(u.user_name));
}
//重写hansCode方法
public int hashCode(){
return this.user_id.hashCode()*this.user_name.hashCode();
}
/*String的hashCode()写法如下
public int hashCode()
{
int i = this.hash;
if (i == 0) {
int j = this.offset;
char[] arrayOfChar = this.value;
int k = this.count;
for (int l = 0; l < k; ++l) {
i = 31 * i + arrayOfChar[(j++)];
}
this.hash = i;
}
return i;
}
*/
}
//新建测试类
package utilbag;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
public class TestUtil {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//List序列的用法
System.out.println("/***************测试List的用法*****************************/");
List<String> list=new ArrayList<String>();
list.add("100");
list.add("200");
list.add("300");
/***************Iterator单项向前遍历*****************************/
Iterator<String> itera=list.iterator();
while(itera.hasNext()){
System.out.println(itera.next());
}
/***************ListIterator双向遍历*****************************/
ListIterator<String> ite=list.listIterator(2);//从第3个开始遍历
/***************向后遍历*****************************/
while(ite.hasNext()){
System.out.println(ite.next());//指下一个元素
System.out.println(ite.nextIndex());//指下一个元素的下标
}
/***************向前遍历*****************************/
while(ite.hasPrevious()){
System.out.println(ite.previous());//指前一个元素
System.out.println(ite.previousIndex());//指上一元素的下标
}
//Set的用法
System.out.println("/***************测试Set的用法*****************************/");
Set<String> set=new HashSet<String>();
set.add("1");
set.add("2");
set.add("1");//重复的元素不会加到set集合中,加入的对象必须事先hashcode
set.add("3");
Iterator<String> it=set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//打印出:3,2,1这3个元素
Set<User> su=new HashSet<User>();
User u1=new User("1","光光");
System.out.println(u1.hashCode());
su.add(u1);
User u2=new User("2","明明");
su.add(u2);
User u3=new User("3","天天");
su.add(u3);
User u4=new User("3","天天");
su.add(u4);
//注意不重写hashcode的方法则结果会是4个user,重写了hashcode方法,加到set中的结果是3条。//这个就是set容器不允许重复的实现方法
System.out.println("u3.hashCode()="+u3.hashCode());
System.out.println("u4.hashCode()="+u4.hashCode());
System.out.println("u3==u4结果为:"+(u3==u4));//不一样是因为他们的地址是不一样的
//在HashMap HashSet中,hashCode()是判断放进容器里的两个对象是否相等的依据。
//如果自己写容器,那就修改覆写改方法
System.out.println("u3.equals(u4)结果为:"+(u3.equals(u4)));
/**********怎么会都不相等呢,试试重写他们的equals和hashcode看看************/
Iterator<User> ituser=su.iterator();
while(ituser.hasNext()){
User uu=(User)ituser.next();
System.out.println(uu.hashCode());
System.out.println(uu);
}
String s="hello";
String s1=s;
String s2=s;
System.out.println("s1==s2:"+(s1==s2));
System.out.println("/***************测试Map的用法*****************************/");
Map<String, String> map=new HashMap<String, String>();
map.put("100", "100");
map.put("100", "200");
map.put("200", "300");
map.put("300", "400");
map.put("400", "500");
Iterator<String> imap=map.keySet().iterator();
while(imap.hasNext()){
String k=imap.next();
System.out.println(map.get(k));
//打印出来的值为400、300、500、200(无序)说明map不允许有重复的键(值可以重复)
}
map.clear();
map.put("100", "100");
map.put("500", "500");
map.put("200", null);
map.put("300", null);
map.put("400", null);
Iterator<String> iimap=map.keySet().iterator();
while(iimap.hasNext()){
String k1=iimap.next();
System.out.println(map.get(k1));
//System.out.println(iimap.get(k1));
//打印出来的值为null,null,null,100,500(无序)说明map不允许有重复的键(值可以重复,而且可以为null)
}
Iterator<Entry<String, String>> ie=map.entrySet().iterator();
while(ie.hasNext()){
Map.Entry<String, String> mp=ie.next();
System.out.println(mp.getKey()+":"+mp.getValue());
//打印出来
//300:null
//200:null
//400:null
//100:100
//500:500
}
map.clear();
map.put(null, null);
map.put(null, null);
map.put("100", "2");
map.put("100", null);
Iterator ie1=map.entrySet().iterator();
while(ie1.hasNext()){
Map.Entry<String, String> mpp=(Map.Entry<String, String>)ie1.next();
System.out.println(mpp.getKey()+":"+mpp.getValue());
//打印出来只有一个null:null,100:null因为它覆盖了前面的100:2
//键值不允许重复
}
}
}
总结:
1.在HashMap HashSet中,hashCode()是判断放进容器里的两个对象是否相等的依据。如果自己写容器,那就修改覆写改方法 。
2.判断2个对象相等是看2个对象的地址是否相等。
3.判断2个对象相等必须同时重写equals方法和hashcode方法。例如像set中添加2个user对象,缺少2个方法中的任何一个都不可以。
4.看java源码发现,
当new 一个set时,它是在构造函数中new一个map(它的实现是基于map的)
调用set的add方法时,传过去的值是调用的是map的put方法
put(set的值当作键,new object()当作值);
put时,它使用到了hashcode和equals方法
源码如下:
set中:
public HashSet()
{
this.map = new HashMap();
}
public boolean add(E paramE)
{
return (this.map.put(paramE, PRESENT) == null);
}
map中:
public V put(K paramK, V paramV)
{
if (paramK == null)
return putForNullKey(paramV);
int i = hash(paramK.hashCode());
int j = indexFor(i, this.table.length);
for (Entry localEntry = this.table[j]; localEntry != null; localEntry = localEntry.next)
{
Object localObject1;
if ((localEntry.hash == i) && ((((localObject1 = localEntry.key) == paramK) || (paramK.equals(localObject1))))) {
Object localObject2 = localEntry.value;
localEntry.value = paramV;
localEntry.recordAccess(this);
return localObject2;
}
}
this.modCount += 1;
addEntry(i, paramK, paramV, j);
return null;
}
现在我们知道了为什么set是不允许要加入的元素重复的了,而且要加入set的元素必须是重写了hashcode和equals,否则不能实现限制重复添加元素的功能(即set的本质,当然主要是对对象类型来说的)。
分享到:
相关推荐
List,set,Map 的用法和区别 List,set,Map 的用法和区别
// java中对象容器主要有Set,List和Map三个接口类。 // 迭代器(Iterator)模式,又叫做游标(Cursor)模式。 // GOF给出的定义为:提供一种方法访问一个容器(container)对象中的各个元素, // 而又不需暴露该...
Collection,List,Set和_Map用法和区别
详细介绍了java中的list、map、set的存储方式及使用方法,涵盖了多个java大侠的见解,让读者充分了解list、map、set的区别和使用
java集合类Collection、List、Set、Map的用法详解,很好的资源!
虽然您总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;因此,允许您更改基本的数据结构而不必改变其它代码。 · Collection 接口是一组允许重复的对象。 · Set 接口继承 Collection,...
c++容器list、vector、map、set区别 list 封装链表,以链表形式实现,不支持[]运算符。 对随机访问的速度很慢(需要遍历整个链表),插入数据很快(不需要拷贝和移动数据,只需改变指针的指向)。 新添加的元素,...
Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set,而不关心它的顺序–否则应该使用List)。Map同样对每个元素保存一份,但这是基于”键”的,Map也有内置的排序,因而不关心...
主要介绍了Java中的Set、List、Map的用法与区别,需要的朋友可以参考下
65、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别 17 66、HashMap和Hashtable的区别 17 67、说出ArrayList,Vector, LinkedList的存储性能和特性 17 68、java中有几...
这种差别的原因与 Set 和 Map 在 Java 库中使用的方法有关。Map 的典型应用是访问按关键字存储的值。它支持一系列集合操作的全部,但操作的是键-值对,而不是单个独立的元素。因此 Map 需要支持 get() 和 put() 的...
主要介绍了Java集合定义与用法,结合实例形式总结分析了Java集合中Set、List和Map相关概念、功能、用法及操作注意事项,需要的朋友可以参考下
在使用 list、set 或 map遍历删除某些元素时可以这样使用,如下所示
java中各种集合的用法 Java集合Collection、List、Set、Map使用详解
2、使用方法如下: public List<V> pipelineGet(Set<K> keys){ return rt.opsForPipeline().get(keys); } public void pipelineSet(Map,V> valueMap){ redisTemplate.opsForPipeline().set(valueMap); } ...
掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet...1、集合中的List、Set、Map有哪些不同? 2、为什么使用集合框架,而尽可能少用数组作为存储结构? 3、如何使用TreeSet实现第一题?
以List、Set、Map集合容器为例: // 创建List接口对象 List<String> list = new ArrayList(); list.add("item") String item = list.get(0); // 创建Set接口对象 Set<String> set = new HashSet(); set.add("item...
通过对这两个类的熟悉,能够将List、Set和Map三大类的基本用法掌握。另外它的几个辅助类要掌握:Iterator和Collections。Collections类 提供容器的一些通用工具,比如排序。而说到排序,就牵扯出了比较器:...
Collection接口是List、Set和Queue接口的父接口,定义了存取一组对象的方法。Collection接口继承自Iterable接口,这意味着可以通过for-each循环遍历集合元素。 List接口是有序的集合,可以包含重复的元素。List接口...