• 容器


    数组是保存一组对象的最有效的方式,如果你想保存一组基本类型数据,也推荐这样方式,但是数据具有固定的尺寸,而在更一般的情况中,你在程序时并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,因此数组尺寸固定显得过于受限了。java实用类库提供了一套想当完整的容器类来解决这个问题,其中基本的类型是List,Set,Queue和Map。
    下图是简单的容器分类图:(下图来自《thinking in java》第十一章)

    为了更加直观的记忆,简化上图:

    java容器大致分为继承Collection接口和继承Map接口两大类。继承自Collection接口的容器,又分为Set,List接口:
    1.Interface List
    Type Parameters:
    E - the type of elements in this list

    是Collection的子接口,实现了List接口的容器类中的元素是有序的,且可以重复
    List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
    JDK提供的实现List接口的容器类有AbstractList, AbstractSequentialList, ArrayList, AttributeList, CopyOnWriteArrayList, LinkedList, RoleList, RoleUnresolvedList, Stack, Vector

    2.Interface Set
    Type Parameters:
    E - the type of elements maintained by this set

    是Collection的子接口,实现了Set接口的容器类的元素是无序的,但是不可以重复,JDK提供的实现了Set接口容器类有AbstractSet, ConcurrentHashMap.KeySetView, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet

    Interface Map

    Type Parameters: K - the type of keys maintained by this map V - the type of mapped values

    实现Map接口的类用来存储键-值对
    Map接口的实现类有HashMap和TreeMap等
    Map类中存储的键-值对通过键来标识,所以键值不能重复
    jdk提供实现Map容器类有:AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable,IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings,TabularDataSupport, TreeMap, UIDefaults, WeakHashMap

    具体可以参考官方API,有详细的说明。http://docs.oracle.com/javase/8/docs/api/index.html

    下面看一段代码:

    点击(此处)折叠或打开

    1. public class Collection1 {
    2.   
    3.     private int i;
    4.     private String name;
    5.     
    6.     public Collection1(int i,String name) {
    7.         // TODO 自动生成的构造函数存根
    8.         this.i = i;
    9.         this.name = name;
    10.     }
    11.     
    12.     public int geti(){
    13.         
    14.         return i;
    15.     }
    16.     
    17.     public String getName(){
    18.         
    19.         return name;
    20.     }
    21.     
    22.      public String toString(){
    23.         
    24.         return i + "-" +name +" ";
    25.     }
    26. }
    27. public class Test {
    28.    
    29.     public static void main(String[] args){
    30.         
    31.         ArrayList<Collection1> c = new ArrayList<Collection1>();
    32.         c.add(new Collection1(1, "diy"));
    33.         c.add(new Collection1(2,"os"));
    34.         c.add(new Collection1(3, "Lios"));
    35.        
    36.         for(int i=0;i<c.size();i++){
    37.         System.out.print(c.get(i).geti() + " ");
    38.      }
    39.     /*
    40.     for(Collection1 cc :c){

          System.out.print(cc.geti() + " ");
      }
      */
    41.     }
    42. }
    上面我们利用ArrayList容器类来盛放Collection1对象,如果要从容器中取出对象,只有上面的两种方式么?当然不是,还记得Object类中的toString()方法吧,通过重写该方法,也可以打印出我们想要的结果。下面介绍另一种:

    点击(此处)折叠或打开

    1. public class Test {
    2.    
    3.     public static void main(String[] args){
    4.         
    5.         ArrayList<Collection1> c = new ArrayList<Collection1>();
    6.         c.add(new Collection1(1, "diy"));
    7.         c.add(new Collection1(2,"os"));
    8.         c.add(new Collection1(3, "Lios"));
    9.         
    10.         Iterator<Collection1> ite = c.iterator(); //ArrayList类中实现iterator()方法,作用:Returns an iterator over the elements in this list in proper sequence.

    11.         
    12.          while(ite.hasNext()){
    13.              
    14.              Collection1 t = ite.next();
    15.              System.out.print(t.geti() + " ");
    16.          }
    17.      }
    18.   }
    Iterator是什么?那么查下API先:

    Interface Iterator
    Type Parameters:
    E - the type of elements returned by this iterator
    原来它是接口,下面简单的介绍下:
    Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作
    Iterator接口定义了以下的方法:
    default void : forEachRemaining(Consumer action)
    Performs the given action for each remaining element until all elements have been processed or the action throws an exception.
    boolean hasNext():判断游标右边是否有元素
    E next():返回游标右边的元素并将游标移动到下一个位置
    default void remove():删除游标左面的元素在执行完next之后该操作只能执行一次

    原来它是为了方便对容器内元素更好地遍历操作!关于更详细的内容,请读者参考API.

    如果想删除容器中的元素怎么办呢,查看api文档发现,提供我们remove(Object o)方法,那就好办啊!

    点击(此处)折叠或打开

    1. public class Test {
    2.    
    3.     public static void main(String[] args){
    4.         
    5.         ArrayList<Collection1> c = new ArrayList<Collection1>();
    6.         c.add(new Collection1(1, "diy"));
    7.         c.add(new Collection1(2,"os"));
    8.         c.add(new Collection1(3, "Lios"));
    9.         
    10.         c.remove(new Collection1(1,"diy"));
    11.         Iterator<Collection1> ite = c.iterator();
    12.         
    13.          while(ite.hasNext()){
    14.              
    15.              Collection1 t = ite.next();
    16.              System.out.print(t.geti() + " ");
    17.          }
    18.     }
    19. }
    咦?怎么打印结果没有变化啊?不是删除了么?c.remove(new Collection1(1,"diy"));我想有些朋友会这样疑问,其实在调用remove()时,系统会调用equals(Object o),如果容器中要删除的对象this,和remove(Object o)函数的参数o相等的话,equals()返回true,否则返回false。对于自定义类型,那么需要重写equals()方法和hashCode()方法,两个equals的对象,那么它们的hashcode也是相等的。上述中remove(new Collection1(1,"diy")),传入的Collection1的对象,和add(new Collection1(1,"diy"))中添加的对象,在堆中是两片不同的内存区域,所以是不同的对象,当然不会删除!那么没有办法删除了么,当然不是,我们可以通过对象引用的方式来删除:

    点击(此处)折叠或打开

    1. public class Test {
    2.    
    3.     public static void main(String[] args){
    4.         
    5.         ArrayList<Collection1> c = new ArrayList<Collection1>();
    6.         
    7.         Collection1 diy = new Collection1(1, "diy");
    8.         c.add(diy);
    9.         c.add(new Collection1(2,"os"));
    10.         c.add(new Collection1(3, "Lios"));
    11.         
    12.         c.remove(diy);
    13.         Iterator<Collection1> ite = c.iterator();
    14.         
    15.          while(ite.hasNext()){
    16.              
    17.              Collection1 t = ite.next();
    18.              System.out.print(t.geti() + " ");
    19.          }
    20.    }
    21. }


    简单的修改Test.java:

    点击(此处)折叠或打开

    1. public class Test {
    2.    
    3.     public static void main(String[] args){
    4.  HashSet<Collection1> c = new HashSet<Collection1>();
    5.         
    6.         Collection1 ss = new Collection1(1,"diy");
    7.         c.add(ss);
    8.         c.add(new Collection1(2, "os"));
    9.         c.add(new Collection1(3, "Lios"));
    10.         c.add(ss);
    11.         Iterator<Collection1> ite = c.iterator();
    12.         
    13.          while(ite.hasNext()){
    14.              
    15.              Collection1 t = ite.next();
    16.              System.out.print(t.geti() + " ");
    17.          
    18.          
    19.        }
    20.     }
    21. }
    打印结果无序,而且不会出现重复对象,其中如何判断放入的是不是同一对象也是用equals(Object o)来实现。


    简单的修改Test.java:

    点击(此处)折叠或打开

    1. public class Test {
    2.    
    3.     public static void main(String[] args){
    4.     HashMap<String, Integer> A = new HashMap<String, Integer>();
    5.      A.put("One", 1);
    6.      A.put("Two", 2);
    7.      A.put("Three", 3);
    8.      System.out.println(A.get("One"));
    9. }
    10. }
    上述put(K key, V value)中,第二个参数是Integer类型,但是直接写int类型数字,无错误,这是Java自动打包解包缘由:
    自动将基础类型转换为对象
    自动将对象转换为基础类型

    本文中没有提及LinkedList类,和Interface Queue及其子类,因为后续有文章提及Java中的算法数据结构,当然java封装了其中的算法,通过查阅API文档,可以很好地掌握。 
    文中如有错误之处,请读者指正 !
     
     
  • 相关阅读:
    Lucene:(一)建立索引文件:2。建立索引文件(一)
    Lucene:(一)建立索引文件:2。建立索引文件(二)Segment文件
    92.外边距设置 Walker
    99.元素居中及样式重置 Walker
    94.外边距踩坑 Walker
    101.列表属性 Walker
    97.boxsizing属性 Walker
    98.溢出隐藏 Walker
    95.内边距设置 Walker
    96.内边距和边框踩坑 Walker
  • 原文地址:https://www.cnblogs.com/diy-os/p/4929835.html
Copyright © 2020-2023  润新知