`

List和Set及Map用法(1)

阅读更多
本节主要是为了搞懂
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 的用法和区别 List,set,Map 的用法和区别

    java中set、list和map的使用方法实例

    // java中对象容器主要有Set,List和Map三个接口类。 // 迭代器(Iterator)模式,又叫做游标(Cursor)模式。 // GOF给出的定义为:提供一种方法访问一个容器(container)对象中的各个元素, // 而又不需暴露该...

    Collection,List,Set和_Map用法和区别

    Collection,List,Set和_Map用法和区别

    java中的list、map、set存储方式及使用方法

    详细介绍了java中的list、map、set的存储方式及使用方法,涵盖了多个java大侠的见解,让读者充分了解list、map、set的区别和使用

    Java集合Collection、List、Set、Map使用详解

    java集合类Collection、List、Set、Map的用法详解,很好的资源!

    JAVA集合(List,Set,Map)

    虽然您总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;因此,允许您更改基本的数据结构而不必改变其它代码。 · Collection 接口是一组允许重复的对象。 · Set 接口继承 Collection,...

    c++容器list、vector、map、set区别与用法详解

    c++容器list、vector、map、set区别 list 封装链表,以链表形式实现,不支持[]运算符。 对随机访问的速度很慢(需要遍历整个链表),插入数据很快(不需要拷贝和移动数据,只需改变指针的指向)。 新添加的元素,...

    java中list、set和map 的区别

    Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set,而不关心它的顺序–否则应该使用List)。Map同样对每个元素保存一份,但这是基于”键”的,Map也有内置的排序,因而不关心...

    Java中的Set、List、Map的用法与区别介绍

    主要介绍了Java中的Set、List、Map的用法与区别,需要的朋友可以参考下

    java面试宝典

    65、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别 17 66、HashMap和Hashtable的区别 17 67、说出ArrayList,Vector, LinkedList的存储性能和特性 17 68、java中有几...

    精通java集合框架--List,Set..

    这种差别的原因与 Set 和 Map 在 Java 库中使用的方法有关。Map 的典型应用是访问按关键字存储的值。它支持一系列集合操作的全部,但操作的是键-值对,而不是单个独立的元素。因此 Map 需要支持 get() 和 put() 的...

    Java集合定义与用法实例总结【Set、List与Map】

    主要介绍了Java集合定义与用法,结合实例形式总结分析了Java集合中Set、List和Map相关概念、功能、用法及操作注意事项,需要的朋友可以参考下

    stl容器set,map,vector之erase用法与返回值详细解析

    在使用 list、set 或 map遍历删除某些元素时可以这样使用,如下所示

    java中各种集合的用法

    java中各种集合的用法 Java集合Collection、List、Set、Map使用详解

    spring-data-redis支持批量操作

    2、使用方法如下: public List&lt;V&gt; pipelineGet(Set&lt;K&gt; keys){ return rt.opsForPipeline().get(keys); } public void pipelineSet(Map,V&gt; valueMap){ redisTemplate.opsForPipeline().set(valueMap); } ...

    实验05 Java集合.doc

    掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet...1、集合中的List、Set、Map有哪些不同? 2、为什么使用集合框架,而尽可能少用数组作为存储结构? 3、如何使用TreeSet实现第一题?

    JDK1.7 32位

    以List、Set、Map集合容器为例: // 创建List接口对象 List&lt;String&gt; list = new ArrayList(); list.add("item") String item = list.get(0); // 创建Set接口对象 Set&lt;String&gt; set = new HashSet(); set.add("item...

    Java学习过程中应该理解的一些重点内容

    通过对这两个类的熟悉,能够将List、Set和Map三大类的基本用法掌握。另外它的几个辅助类要掌握:Iterator和Collections。Collections类 提供容器的一些通用工具,比如排序。而说到排序,就牵扯出了比较器:...

    40道java集合面试题含答案(很全很详细)

    Collection接口是List、Set和Queue接口的父接口,定义了存取一组对象的方法。Collection接口继承自Iterable接口,这意味着可以通过for-each循环遍历集合元素。 List接口是有序的集合,可以包含重复的元素。List接口...

Global site tag (gtag.js) - Google Analytics