• JAVA笔记17-容器之一 图、Collection接口、Iterator接口(重要)


                   

    掌握1136:

    (1)1个图

    (2)1个类:Collections

    (3)3个知识点:For(了解),Generic泛型,Auto-boxing/unboxing(自动打包/解包)

    (4)6个接口:Collection,Set,List,Map,Iterator(迭代器),Comparable

    容器的概念:Java API所提供的一系列类的实例,用于在程序中存放对象。

    小知识点:数组也是容器。集合类与数组的不同之处是:数组的长度是固定的,集合的长度是可变的;数组存放基本数据类型(栈),集合存放对象的引用

       如何选择数据结构?衡量标准--读、改(增删)效率:Array读快改慢,Linked改快读慢,Hash位于前两者之间。

    (HashTable和Vect效率低,已经几乎不用了)

    本节综合例子:

    import java.util.*;
    public class Test{
        public static void main(String[] args){
            Collection<Name> c = new LinkedList<Name>();
            c.add(new Name("Li","Ming"));
            c.add(new Name("Sun","Lei"));
            c.add(new Name("Li","Li"));
            System.out.println(c.remove(new Name("Li","Ming")));//需要equals()方法才能比较相等并移除,需要重写equals()
            System.out.println(c);//依次调用各对象的toString()方法,所以需要重写Name的toString()
            Iterator t = c.iterator();
            while(t.hasNext()){
                System.out.println(t.next());
                t.remove();
            }
            System.out.println(c);
        }
    }
    class Name{
        String fn;
        String ln;
        public Name(String fn, String ln){
            this.fn = fn ;
            this.ln = ln ;
        }
        public boolean equals(Object o){
            if(o instanceof Name){
                Name n = (Name)o ;
                return this.fn.equals(n.fn)&&this.ln.equals(n.ln) ;
            }
            return false ;
        }
        public String toString(){
            return fn+" "+ln ;
        }
    }

    一、继承关系

      J2SDK所提供的容器API位于java.util包中。

      常用的集合有List集合(ArrayList,LinkedList),Set集合(HashSet,TreeSet),Map集合(HashMap,TreeMap)。

    1、Collection接口:(一个一个装)定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。

    (1)Set接口中的数据对象没有顺序、不可重复

    (2)List接口中的数据对象有顺序、可以重复

    注意:重复是指equals

    2、Map接口:(一对一对装)定义了存储“键(key)-值(value)映射对”的方法。

    二、Collection接口

    Collection接口中定义的方法:(它下面所有的类都实现了这些方法)

    举例1:最后一句:c相当于c.toString();该方法在内部的实现是先打印“[”,依次调用每个对象的toString(注意Name类要自己写toString方法),在打印“]”。

    import java.util.*;  //导入java.util包
    public class Test{
        public static void main(String args[]){
            Collection list = new ArrayList(); 
            //可以放入不同类型的元素,但必须都是对象!
            list.add("hello");   
            list.add(new Name("firstname","lastname"));
            list.add(new Integer(100));
            System.out.println(list.size());
            System.out.println(list);//自动调用list.toString()方法,该方法在内部的实现是先打印“[”,依次调用每个对象的toString()方法,再打印“]”
            //注意Name类要重写toString()方法!
        }
    }
    //Name
    class Name{
        private String firstName;
        private String lastName;
        public Name(String firstName,String lastName){
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String toString(){  //注意toString()方法的定义!
            return firstName + " " + lastName ;
        }
    }

    输出:

    3  

    [hello,firstname lastname,100]

    举例2:

    import java.util.*;  //导入java.util包
    public class BasicContainer{
        public static void main(String args[]){
            Collection c = new HashSet(); 
            c.add("hello");   
            c.add(new Name("firstname","lastname"));
            c.add(new Integer(100));
            //调用remove时,依次使用该对象equals方法与remove中的对象比较
            c.remove("hello");
            System.out.println(c.remove(new Integer(100)));//remove成功,返回true
            System.out.println(c.remove(new Name("firstname","lastname")));//remove失败,返回false。因为Name类没有重写equals()方法
            System.out.println(c);
    
        }
    }
    //Name
    class Name{
        private String firstName;
        private String lastName;
        public Name(String firstName,String lastName){
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String toString(){  
            return firstName + " " + lastName ;
        }
    }

    输出:

    true

    false

    [firstname lastname]

    补充知识:两个对象如果equals,则其HashCode相等。当该对象作为Map中的key时,会使用hashCode()方法重写该对象的equals()时,必须重写hashCode()。两个对象equals,那么应保证它们的hashCode相等。如下:

    import java.util.*;  //导入java.util包
    public class BasicContainer{
        public static void main(String args[]){
            Collection c = new HashSet(); 
            c.add("hello");   
            c.add(new Name("firstname","lastname"));
            c.add(new Integer(100));
            //调用remove时,依次使用该对象equals方法与remove中的对象比较
            c.remove("hello");
            System.out.println(c.remove(new Integer(100)));//remove成功,返回true
            System.out.println(c.remove(new Name("firstname","lastname")));//remove失败,返回false
            System.out.println(c);
    
        }
    }
    //Name
    class Name{
        private String firstName;
        private String lastName;
        public Name(String firstName,String lastName){
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String toString(){  
            return firstName + " " + lastName ;
        }
        public boolean equals(Object obj) {//注意equals方法的定义!
            if(obj instanceof Name){
                Name name = (Name) obj;
                return (firstName.equals(name.firstName))&&(lastName.equals(name.lastName));
            }
                return super.equals(obj);//???
        }
        public int hashCode(){
            return firstName.hashCode();
            //因为Sun字符串已经实现了hashCode()方法,所以这里使用字符串的hashCode()方法
            //如果自己实现很难。
        }
    }

    输出:

    true

    true

    []

    三、Iterator接口

    问题:如何遍历集合中的每个元素?

      例如ArrayList以数组作为底层实现的;LinkedList是以链表为底层实现的。遍历的方式是不同的,所以由每一个类对象实现自己的遍历方法(返回一个实现了Iterator接口的对象)。

      Iterator就是一个统一遍历Collection下面所有元素的方法的接口。简单理解为一个指针(游标),指在第一个元素的左侧。

      通常,遍历集合都是通过迭代器(Iterator)实现。Collection接口中的iterator()方法可返回在此Collection进行迭代的迭代器。其实也就是返回一个实现了Iterator接口的对象。(有多态!)Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。

      Iterator接口定义了如下方法:

    举例1:

    import java.util.*;  //导入java.util包
    public class Muster{
        public static void main(String args[]){
            Collection list = new ArrayList(); //实例化集合类对象
            list.add("a");   //向集合添加元素
            list.add("b");
            list.add("c");
            Iterator it = list.iterator(); //创建迭代器
            while(it.hasNext()){  //判断是否有下一个元素
                String str = (String) it.next(); //获取集合中元素
                System.out.println(str);
            }
        }
    }

    输出:

    a

    b

    c

    举例2:

    import java.util.*;  //导入java.util包
    public class Test{
        public static void main(String args[]){
            Collection c = new HashSet(); //注意HashSet是无序的!
            c.add(new Name("f1","l1"));
            c.add(new Name("f2","l2"));
            c.add(new Name("f3","l3"));
            Iterator i = c.iterator();
            while(i.hasNext()){
                Name n = (Name) i.next();//next()返回值为object类型,所以此处需要转换为相应类型
                System.out.println(n.getFirstName()+"");
            }
        }
    }
    //Name
    class Name{
        private String firstName;
        private String lastName;
        public Name(String firstName,String lastName){
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String getFirstName(){
            return firstName;
        } 
    }

    输出:

    f3

    f2

    f1

    举例3:循环内部只能调用Iterator接口的方法,不能调用容器自身的方法。

    Iterator对象的remove方法是在迭代过程中删除元素的唯一安全方法。因为Iterator循环的内部执行了锁定。

    import java.util.*;  //导入java.util包
    public class Test{
        public static void main(String args[]){
            Collection c = new HashSet(); //注意HashSet是无序的!
            c.add(new Name("fff1","l1"));
            c.add(new Name("f2","l2"));
            c.add(new Name("fff3","l3"));
            for(Iterator i = c.iterator();i.hasNext();){
                Name name = (Name) i.next();
                if(name.getFirstName().length()<3){
                i.remove();
                //如果换成c.remove(name);会产生例外??测试过了,输出一样并没有例外
                }
            }
            System.out.println(c);
        }
    }
    //Name
    class Name{
        private String firstName;
        private String lastName;
        public Name(String firstName,String lastName){
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public String getFirstName(){
            return firstName;
        } 
        public String toString(){  
            return firstName + " " + lastName ;
        }
        public boolean equals(Object obj) {
            if(obj instanceof Name){
                Name name = (Name) obj;
                return (firstName.equals(name.firstName))&&(lastName.equals(name.lastName));
            }
                return super.equals(obj);
        }
        public int hashCode(){
            return firstName.hashCode();
        }
    }

    输出:

    [fff1 l1,fff3 l3]

     

     

     

  • 相关阅读:
    .NET Obfuscator Dotfuscator 入门
    查询集合已修改;可能无法执行枚举操作
    泛型(C# 2。0 编程指南) <一>
    在服务器上部署VS 2008 ReportViewer,完美支持中文
    dataGridView 闪烁 和 listview 闪烁 的解决办法。
    Asp.Net 调试客户端脚本
    疑是Microsoft Enterprise Library June 2005的一个小bug (续)
    MagicAjax 0.30版的更新(翻译)
    疑是Microsoft Enterprise Library June 2005的一个小bug
    在web页面中水晶报表显示速度过慢的原因
  • 原文地址:https://www.cnblogs.com/seven7seven/p/3670948.html
Copyright © 2020-2023  润新知