java基础-容器

已经写了一段时间JAVA代码了,但仔细想来,却发现对JAVA的很多方面还是一片迷茫。

利用周末补一下基础知识吧。

 

大致列一下这个周末需要学习的内容

1 容器 (本节内容)

2 线程

3 流 

 

目录

1 接口List Set Collection Comparable 

2 工具类 Collections 

3 Set 的去重原理

4 hashcode equals 的重写

5 Iterator接口实现的的遍历(List Set Map)

一、容器

接口:Collection 接口定义了容器的基本操作,List,Set接口都是Collection的子接口

List接口

List接口的主要实现类有我们常用的ArrayList,LinkList,允许重复且是有序的。

ArrayList与LinkList区别

ArrayList的get,set会比较快,因为LinkList需要移动指针。

LinkList的add,remove会比较快,因为ArrayList需要移动数据。

Collections类提供对List对象进行排序的静态方法,但List里面的对象必须实现comparable接口

例1 Collections打乱顺序的方法shuffle

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class test {
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    
    public static void main(String[] args) {
        List list = new ArrayList();
        test t1 = new test("1","a");
        test t2 = new test("3","C");
        test t3 = new test("2","b");
        list.add(t1);list.add(t2);list.add(t3);
        
        Collections.shuffle(list);  //打乱顺序
//        Collections.sort(list);
        
        for(Object obj: list){
            test res =(test)obj;
            System.out.println(res.getId()+" "+res.getName()+" / hashCode : "+res.hashCode());
        }
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

2 b / hashCode : 12830537
3 C / hashCode : 22068557
1 a / hashCode : 29115481

顺序已经打乱

例2 Collections排序方法sort

Collections.sort(list);

结果 

Exception in thread "main" java.lang.ClassCastException: test.test cannot be cast to java.lang.Comparable
    at java.util.Arrays.mergeSort(Arrays.java:1144)
    at java.util.Arrays.sort(Arrays.java:1079)
    at java.util.Collections.sort(Collections.java:117)
    at test.test.main(test.java:23)

如果List里面的对象没有实现Comparable接口的话,是不能进行排序的,

所以需要改一下代码实现Comparable接口,代码如下。

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class test implements Comparable{//实现Comparable接口
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    
    @Override
    public int compareTo(Object obj) {//把compareTo写完整,按ID排序  --->用对象(obj)的id与自己的id比较大小
        test t = (test)obj;
        return this.id.compareTo(t.getId());
    }
    
    public static void main(String[] args) {
        List list = new ArrayList();
        test t1 = new test("1","a");
        test t2 = new test("3","C");
        test t3 = new test("2","b");
        list.add(t1);list.add(t2);list.add(t3);
        
        Collections.shuffle(list);  //打乱顺序
        Collections.sort(list);
        
        for(Object obj: list){
            test res =(test)obj;
            System.out.println(res.getId()+" "+res.getName()+" / hashCode : "+res.hashCode());
        }
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

1 a / hashCode : 29115481
2 b / hashCode : 19621457
3 C / hashCode : 4872882

排序成功

 

Set接口

Set接口的主要实现类有我们常用的HashSet 是不允许重复且无序的。

Set是如何去重的

1 每当Set需要Add一个对象的时候,会先去找对象的HashCode并检查这个HashCode位置上有没有已经存在的对象

2 如果没有存在对象,就正面不重复可以添加至容器

3 如果存在对象,则通过equal方法进行比较如果不相同则可以添加,如果相同则不添加到容器中

这算法的好处是减少每次添加数据时候的比较次数,比如容器里面已经有N个对象,那么一个个去equal就得比较N次,而这样最多比较1-2次

4 如果每次都是New一个对象放入的时候,如果要需要去重,那么必须重写 int hashCode和equals方法

注意:HashCode通常情况下表示地址,但并不是地址,因为hashCode可以背重写。

getClass().getName() + "@" + Integer.toHexString(hashCode()),jdk对toString方法的实现。

例1 new三个一样内容的对象添加入set容器(不重写hashcode)

package test;

import java.util.HashSet;
import java.util.Set;

public class test {
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }

    public static void main(String[] args) {
        Set set = new HashSet();
        test t1 = new test("1","a");
        test t2 = new test("1","a");
        test t3 = new test("1","a");
        set.add(t1);set.add(t2);set.add(t3);
        for(Object obj: set){
            test res =(test)obj;
            System.out.println(res.getId()+" "+res.getName()+" / hashCode : "+res.hashCode());
        }
    
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

1 a / hashCode : 5184781
1 a / hashCode : 25860399
1 a / hashCode : 33311724

因为每个对象被NEW出来的时候都被新分配了一个内存地址,所以hashcode是不一样的

所以通过了Set的hashcode校验。

 

例2 new三个一样内容的对象添加入set容器,重写hashcode(不重写equals方法)

package test;

import java.util.HashSet;
import java.util.Set;

public class test {
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    @Override //重写了hashCode方法,hashCode都为0
    public int hashCode(){
        return 0;
    }
    

    public static void main(String[] args) {
        Set set = new HashSet();
        test t1 = new test("1","a");
        test t2 = new test("1","a");
        test t3 = new test("1","a");
        set.add(t1);set.add(t2);set.add(t3);
        System.out.println("T1与T2用equals方法进行比较 "+t1.equals(t2));//这里只比较T1和T2
        for(Object obj: set){
            test res =(test)obj;
            System.out.println(res.getId()+" "+res.getName()+" / hashCode : "+res.hashCode());
        }
    
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

T1与T2用equals方法进行比较 false
1 a / hashCode : 0
1 a / hashCode : 0
1 a / hashCode : 0

虽然hashCode已经相同,但通过使用equals方法进行下一步比较的结果是false,所以Set容器判断为并不重复,所以仍然通过了校验

 

例2 new三个name一样,id不一样的对象添加入set容器,重写hashcode、重写equals方法(针对name重复)

package test;

import java.util.HashSet;
import java.util.Set;

public class test {
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    @Override //重写了hashCode方法,hashCode都为0
    public int hashCode(){
        return 0;
    }
    @Override
    public boolean equals(Object obj){
        test t = (test)obj;
        return this.name.equals(t.getName());//这里重写如果名字相同就返回true,否则返回false
    }
    
    public static void main(String[] args) {
        Set set = new HashSet();
        test t1 = new test("1","a");
        test t2 = new test("2","a");
        test t3 = new test("3","a");
        set.add(t1);set.add(t2);set.add(t3);
        System.out.println("T1与T2用equals方法进行比较 "+t1.equals(t2));//这里只比较T1和T2
        for(Object obj: set){
            test res =(test)obj;
            System.out.println(res.getId()+" "+res.getName()+" / hashCode : "+res.hashCode());
        }
    
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

T1与T2用equals方法进行比较 true
1 a / hashCode : 0

重写hashcode和equals的方法使得对象在添加进入Set容器时可以有效的去重。

 

Iterator 接口的遍历
Iterator接口可以对List和Set容器进行遍历

package test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class test {//实现Comparable接口
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    
    public static void iterator(Iterator it){ //iterator 遍历
        while(it.hasNext()){
            test t =(test) it.next();
            System.out.print(t.getName()+"\r\n");
        }
    }
    
    public static void main(String[] args) {
        test t1 = new test("1","BB");
        test t2 = new test("2","AA");
        Set set = new HashSet(); //SET
        set.add(t1);set.add(t2);
        
        List list = new ArrayList(); //LIST
        list.add(t1);list.add(t2);
        
        Iterator it = set.iterator();
        test.iterator(it);
        Iterator it1 = list.iterator();
        test.iterator(it1);
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

结果

AA//SET
BB
BB//LIST
AA

List和Set都有iterator()方法,可以转换为iterator对象进行遍历

 

MAP对象也可以通过自带的keySet()方法转化成Set后进行Iterator进行遍历

package test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class test {//实现Comparable接口
    String name;
    String id;
    test(String id,String name){
        this.id=id;
        this.name=name;
    }
    
    public static void iterator(Iterator it,Map map){ //iterator 遍历 
        while(it.hasNext()){
            String key =it.next().toString();
            test res = (test)map.get(key);
            System.out.println(res.getName());
        }
    }
    
    public static void main(String[] args) {
        test t1 = new test("1","BB");
        test t2 = new test("2","AA");
        
        Map map = new HashMap();
        map.put("1", t1);map.put("2", t2);
        
        Set mapset =map.keySet();
        Iterator it = mapset.iterator();
        test.iterator(it,map);
    }
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
}

1 使用map.keySet转换成set对象

2 转换后调用iterator()转成Iterator对象后进行遍历

3 遍历出的结果为key,调用map.getKey方法获得值

 

posted on 2014-01-19 17:01  sunfan  阅读(251)  评论(0编辑  收藏  举报