zoukankan      html  css  js  c++  java
  • 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()+"
    ");
            }
        }
        
        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方法获得值

  • 相关阅读:
    前端开发中一些好用的软件包。
    LeetCode 26 删除排序数组中的重复项
    算法 主定理
    算法学习计划继续三四个月
    Web Api
    DOM viewport
    CSS OM
    DOM Range Api
    DOM 操作 2
    DOM Event
  • 原文地址:https://www.cnblogs.com/sunfan1988/p/3526029.html
Copyright © 2011-2022 走看看