• java 中的容器(札记)


    创建容器向上转型为接口的时候,有时候,并不是一定可行的,因为有的实现类,在接口的基础添加了自己的方法;比如:List 接口下面的 LinkedList 自己定义了一些方法 ;


    Arrays.asList() 返回值,内部其实是一个 数组;因此,我们不能对其进行 add 、delete 操作。因为这些操作,会改变数组的尺寸,而数组大小是固定的 ;

     List<A1> list = Arrays.asList(new C1(),new A1(),new B1()) ;
     // 编译时不会产生任何警告,但是我们运行就会得到一个异常:不支持的操作 ;
     list.add(new A1());

    在定义 List 的时候,可以使用 Arrays.asList() 的返回值为其赋值;但是在赋值的时候,返回值类型,是根据参数的类型来的,这里会引起问题的;

    即使几个参数是一个 继承体系 中的;

    如果参数类型和泛型不一致的话,会报错;但是只要有一个参数与泛型匹配,那么就不会再报错 ;

    // 类的继承关系
    class A1 {}
    
    class B1 extends A1{}
    
    class C1 extends B1 {}
    
    -------------------------------
    // error ,因为泛型要求是 A1,但是参数中没有这样 A1类型
    List<A1> list = Arrays.asList(new C1(),new B1()) ;
    // oK ,只要一个继承体系中,有一个参数是泛型类型,就OK 
    List<A1> list = Arrays.asList(new C1(),new B1(),new A1()) ;
    

    上面的代码,我们可以看出,很不好,必须要有泛型类型的参数才行,只有其子类,都会报错;

    因此我们需要给 Arrays.asList() 提供一个线索 :Arrays.<泛型>asList() ,这样 Arrays.asList() 就会自动的返回泛型指定的类型,而不是去根据参数来返回具体的类型 ;

    List<A1> list = Arrays.<A1>asList(new C1(),new B1()) ;

    当然我们也可以用 Collections.addAll();会根据第一个参数类型,直接推导出应该返回的类型 ;

    List<A1> list = new ArrayList<>();
    Collections.addAll(list,new C1(),new B1());

    存储元素:

    HashSet HashMap 乱序
    
    TreeSet TreeMap 默认按照自然顺序,我们可以自己传入比较器
    
    LinkedHashSet LinkedHashMap 按照插入顺序
    

    List 中的 remove(xx)removeAll(xx)indexOf(xx)等操作,都用到元素的 equals()方法;因为他们都要判断参数是否在容器里面,这个判断,就需要用到 equals()方法;

    当然上述方法,都有自己的重载版,直接操控角标,那么则用不到 equals()方法 ;

    List 可以在中间插入元素的;想到 List 下面的小弟 LinkedLsitArrayList 就应该不会对其可在中间插入元素的能力感到怀疑 ;


    collectionsAll(a,b,c); 对参数的顺序是不关心的 ;

         List<A1> list = new ArrayList<>();
         list.add(new B1());
         C1 c1 = new  C1();
         C1 c2 = new  C1();
         B1 b1 = new  B1();
         Collections.addAll(list,b1,c1,c2);
         // 对参数的顺序是不做要求的
         List<A1> a1List = Arrays.<A1>asList(c2,c1,b1);
         // 输出 true 
         System.out.println(list.containsAll(a1List));

    a.retainAll(b) 查交集 ;


    迭代器(Iterator)的出现,统一了对容器的遍历操作;

    因为,迭代器的方法:haveNext()next() ;根本就没有出现对具体容器操作的代码;后期即使改变了容器,迭代器的代码也不用改变 ;

    Iterator 迭代器,只能 单向遍历,但是可以遍历任意容器;

    ListIterator 只能遍历 List 集合;但是可以 双向遍历,也可以从任何一个位置开始遍历;还可以返回当前位置的前一个、后一个位置的索引 ;


    SetCollection 具有一样的接口,不像 List 那样,自己添加了一些方法 ;

    HashSet 维护着一个散列函数,该散列函数决定了元素的次序;

    TreeSet 里面维护着红黑树;


    Collection 接口 AND Iterator 方法

    Collection 接口中有许多方法,假如我们要实现这个接口,那么我们将要实现一大堆方法,尽管其中有些方法,我们并不想用;

    官方也考虑到这个问题,因此,官方给出来一个 Collection 接口的直接抽象子类 AbstractCollection ,这样我们就只需要实现 两个方法 iterator() 、size() 即可 ;

    class D1 extends AbstractCollection{
    
        @Override
        public Iterator iterator() {
            return null;
        }
    
        @Override
        public int size() {
            return 0;
        }
    }

    foreach 增强for循环

    只对 数组 和 实现了 Iterator 接口,起作用 ;但是并不是 数组Iterator 类型 ;


    Arrays.asList(c2,c1,b1) 返回值底层是一个数组,对返回值的操作,将直接影响到原数组 ;因此,一次操作是不允许的,比如 add(()、remove()等方法 ;

    如果对返回值进行操作,那么同样影响到原数组 ;

        Integer[] integer = {1,22,33,4,56,21};
        List<Integer> a1List = Arrays.asList(integer);
        a1List.set(0,12) ;
        //  输出的是 12  而不是 1 ;
        System.out.println(integer[0]);

    如果实在需要操作,可以将返回值转成一个真正的 List 类型 ;

         List<A1> a1List = Arrays.<A1>asList(c2, c1, b1);
         List<A1> a1List1 = new ArrayList<>(a1List);
         // 添加元素
         a1List1.add(new A1()) ;
         // 改变元素组。。
  • 相关阅读:
    竖版文字排列实现《金刚般若波罗蜜心经》
    前端气泡效果实现的方式
    纯CSS绘制三角形
    什么是块级格式上下文
    绝对定位元素left、right、top、bottom值与其margin和宽高的关系
    currentColor在CSS的含义
    HTML/css清除浮动的几种方式
    W3C中不同标准的含义
    table表格标签的属性
    输入你的生日某年某月某日,判断这一天是这一年的第几天、星期几?
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665709.html
Copyright © 2020-2023  润新知