• .Net转Java自学之路—基础巩固篇十三(集合)


    集合:

      集合是用于存储对象的一个工具。

      集合与数组的特点

        相同点:都是一个容器

        不同点:

          集合:可以存储对象,只能存储对象,集合长度可变。

          数组:可以存储对象,也可以存储基本数据类型,数组长度固定。

      容器对象有很多种,通过内部的数据结构来区分,数据结构就是一种数据存储方式。

      在不断的将容器对象的相同点抽取的过程中,就出现了集合体系结构,该体系的结构框架称为集合框架。

      最顶层的是一个接口:Collection

      Collection 表示的是一组对象。

    迭代器(Iterator):

      Collection集合中对元素的获取方式:hasNext() 判断是否有值、next() 返回迭代的下一个元素、remover() 删除

      集合容器都具备取出方式,取出方式并不是一个方法,因为一个方法并不足以完成取出,取出是由多个方法来完成的,为了方便使用,将这些方法封装称了对象;该对象在描述时,这些功能会直接使用到具体集合中的数据和集合特点。所以这个取出元素的描述类,就定义在集合的内部,也就是一个内部类。

      因为这个类在直接访问集合中的数据,根据集合自身的数据结构特点,将具体的方法都定义完成后,需要将对象对外提供出去让用户使用,所以就暴露了一个方法,来完成对这个内部类对象的访问。

      为了提高扩展性,发现只要是容器,就具备取出功能,但数据结构不同,取出的具体实现一样,这时为了扩展,就抽取了一个接口 Iterator (迭代器)。

    Collection coll=new ArrayList();
    coll.add("元素1");
    coll.add("元素2");
    coll.add("元素3");
    Iterator iter=coll.iterator();
    while(iter.haxNext()){
      iter.next();  
    }
    //
    for(Iterator iter=coll.iterator();iter.haxNext()){
      iter.next();  
    }
    View Code

      只要是在 Collection 集合体系中,迭代器就是通用的取出方式。

      在进行迭代器使用时,next() 在循环中只能定义一个,定义多个会导致数据错误;当next()没有获取到元素时,会发生NoSushElementException异常。

      用迭代器取出自定义对象的元素时,在 next() 后要进行类型的转换操作。

    Collection coll=new ArrayList();
    coll.add(new ClassName("元素1"));
    coll.add(new ClassName("元素2"));
    coll.add(new ClassName("元素3"));
    for(Iterator iter = coll.iterator(); iter.haxNext()){
      ClassName cn=(ClassName)iter.next();
      cn.ClassNameMethod();  
    }
    View Code

    集合List:  extends Collection

      该容器的元素有序,存储顺序和取出顺序一致。该集合中的元素都有索引(角标),可以存储重复的元素。

    //List常见基本操作
    List list=new ArrayList();
    //
    list.add("元素");
    list.add(1,"元素");//指定索引位插入元素,其他元素以此延续
    //
    list.remover(1);//指定索引位删除元素。被删除的元素会被返回
    //
    list.set(1,"New元素");//替换指定索引位元素。会返回被修改掉的元素。
    //
    list.get(1);//获取索引位指定的元素。
    list.indexOf("元素");//获取元素第一次出现的位置(索引)
    list.subList(int,int);//根据头尾角标获取子列表,返回List集合

    列表迭代器:ListIterator

      在进行迭代过程中,若出现了迭代器和容器同时对元素进行操作的情况,很容易引发ConcurrentModificationException(并发修改)异常。对于List集合解决此类异常就用 ListIterator 列表迭代器

      ListIterator 时 Iterator 的子接口。并提供了更多的迭代过程中的操作方法;该迭代器只能用于 List 集合。

    //ListIterator 常见基本功能
    List list=new ArrayList();
    list.add("元素1");
    list.add("元素2");
    list.add("元素3");
    list.add("元素4");
    
    ListIterator lit=list.listIterator();
    
    lit.haxNext();//判断 是否有后一个元素
    lit.haxPrevious();//判断 是否有前一个元素
    lit.add();//添加
    lit.set();//修改
    lit.next();//取后一个元素
    lit.previous();//取前一个元素

      ArrayList

        底层数据结构是数组结构。实现不同步;jdk1.2 版本 ArrayList 替换 Vector

        ArrayList 对元素的查询快,增、删 慢

        判断元素是否相同时,底层的依据时 equals() 方法;无论时 contains() 还是 remover() 都会去使用 equals() 来判断元素是否相同。所以在往 ArrayList 集合中存储自定义元素时,最好建立该元素特有的判断对象是否相同的依据。也就是覆盖 equals() 方法。

      Vector

        底层数据结构是数组结构。实现同步;jdk1.0版本

        Vector 对元素的增、删、查 都很慢

        elements()方法返回枚举(Enumeration)该功能与迭代器的功能重复;由于枚举(Enumeration)书写麻烦,故被迭代器替换掉。

    Vector vt=new Vector();
    vt.addElement("元素1");
    vt.addElement("元素2");
    vt.addElement("元素3");
    vt.addElement("元素4");
    
    for(Enumeration ent=vt.elements(); ent.hasMoreElements()){
      ent.nextElement();  
    }

      可变长度数组

        ArrayList 内部封装了一个默认长度为10的数组。当超出长度时,集合内部会自动生成一个新的数组;将原数组中的数据复制到新的数组中;ArrayList 新的数组长度是原数组的50%延长;Vector 新的数组长度是原数组的100%延长。

      LinkedList

        底层数据结构是链表结构。实现不同步;jdk1.2 版本;

        LinkedList 对元素的增、删效率高,但查询慢

    //特有方法
    
    //
    addFirst();
    addLast()
    
    //获取元素,集合长度不变
    getFirst();
    getLast();
    //jdk1.6 版本后被下面俩个方法替代。若集合中没有元素,该方法不会抛出异常,而返回null
    peekFirst();
    peekLast();
    
    //获取被删除的元素,集合长度改变
    removeFirst();
    removeLast();
    //jdk1.6 版本后被下面俩个方法替代。若集合中没有元素,该方法不会抛出异常,而返回null
    offerFirst();
    offerLast();

    集合Set:  extends Collection

      该容器的元素无序;不可以重复元素。Set 接口的取出元素的方法只有迭代器。

      !~ HashSet:

        底层数据结构为哈希表。哈希表这种结构其实就是对哈希表的存储;而且每一个对象都有自己的哈希表。因为 Object 基类中有一个 hashCode() 方法。

        存储自定义对象并且要保证元素的唯一性。HashSet 保证元素的唯一性主要依赖与 hashCode() 和 equals() 方法。

        当元素的哈希值不同时,元素都有自己的独立位置,不需要再判断元素的 equals() 方法。

        当元素的哈希值相同时,这时元素再哈希表中的位置相同,就需要判断一次元素的内容是否相同;调整元素的 equals() 方法进行一致比较;当这俩个元素不相同时,会存储在一个哈希值上;故、需覆盖 hashCode() 和 equals() 方法。而且需要依据对象的特有条件建立 hashCode() 和 equals() 的具体实现。

        判断包含、删除都是依据 hashCode() 。当 hashCode() 相同时,再判断 equals() 方法

      !~ TreeSet:

        对 Set 集合中的元素进行排序。数据结构为二叉树结构;可以提高排序性能。

        自定义元素本身不具备比较性,TreeSet 集合是无法对元素进行排序的。所以在自定义对象时,需要对象具备一个比较功能。而 Java 已经提供了接口,可以让自定义的对象具备比较性。需要实现 Comparable 接口。

        根据比较方法 compareTo() 的返回值来确定元素的唯一性;返回0,则相同。自定义对象需要覆盖 compareTo() 方法。这称为:元素的自然排序。

        如果元素本身的比较方式无法满足应用,那么 可以让集合本身具备比较性,就是定义一个类,实现 Comparator 接口,覆盖 compare() 方法。将Comparator 接口的子类对象作为参数传递给 TreeSet 集合的构造函数即可。

        当元素自身具备比较性,同时 TreeSet 集合也具备比较器,这时以比较器为主。

    泛型:

      集合中存储了不同类型的对象,获取时,在运行时容易发生ClassCastException类型转换异常。所以在存储时明确集合要操作的数据类型来避免该异常的发生。

      定义集合时,通过<>来明确元素的类型。这中定义的方式称为:泛型

      优点:

        1、运行时出现的ClassCastException 异常转移到编译时期。

        2、泛型的出现避免了强制转换的麻烦。

      泛型其实时 jdk1.5版本后出现的安全机制。

    ArrayList<String> list=new ArrayList<String>();
    list.add("元素");
    list.add("元素1");
    
    for(Iterator<String> iter=list.iterator();iter.hasNext()){
        iter.next();
    }

      泛型的使用其实就是给<>传递实际参数,而这个参数就是一个具体的引用数据类型。

      当类要操作的引用数据类型不确定时,可以使用泛型来定义,也就是定义一个类型参数,将具体的类型作为实际参数传递给<>

      当泛型定义在类上,该泛型作用整个类。建立对象时,就明确了具体类型。那么凡是使用了类上定义的泛型的方法,操作的类也就固定了。

      当类中定义 static 方法时,静态方法不可以直接访问类上的泛型;因为类上的泛型只有通过建立对象才可以明确泛型。那么静态方法若操作的引用数据类型不确定,只能将泛型定义在方法上。在静态方法上定义泛型必须定义在 static 关键字之后。

      当发放中操作的应用数据类型不确定,而且和对应的对象执行的类型也不一定一致。这时就将泛型定义在方法上。

    //泛型接口
    interface Inter<T>{
      public void method(T t);  
    }

    泛型通配符:?

      ?  代表任意类型。

    public static void method(Collection<?> coll){
      for(Iterator<?> iter=coll.iterator(); iter.hasNext()){
          iter.next();
      }  
    }

      定义T只能固定一种类型,定义 ? 可以是任意类型。

      泛型限定:

        ? extends E  接收 E 类型 或 E 的子类型

        ? super E   接收 E 类型 或 E 的父类型

    Map集合:

      特点:

        1、双列集合,Collection 是单列集合。

        2、Map 一次存储一对元素,同是键值对的形式,键和值有对应关系。Collection 是一次存储一个元素。

    //常见功能:
    //
    put(k,v);//返回的是v;将键和值存储 Map 集合,当存入相同的 k 时,新值 v 会覆盖原来的值,并返回原来的值。
    putAll(map);
    
    //
    clear();
    remove(k);//根据键删除对应的值,返回被删除的值。
    
    //
    containsKey(Object key);
    containsValue(Object value);
    isEmpty();
    
    //
    size();//获取Map 元素个数
    get(k);//根据键获取值,还可以判断某个键是否存在的依据。
    Collection values();//获取Map 集合中所有的值。
    Set keySet();//获取Map 集合中所有的键
    Set entrySet();//获取键值对的映射关系。将映射关系封装成对象存入Set 集合

      Map 集合中没有迭代器,迭代器是在 Collection 集合中具备的。

      Map 集合的取出元素的原理,就是将 Map 集合转成 Set 集合,再进行迭代。

      HashTable:

        底层是哈希表数据结构;实现同步。不允许 null 作为键、null 作为值。

        Peoperties:用于配置文件的定义和操作,使用频率高,同时键和值都是字符串。是集合中可以和IO技术相结合的对象。详细见IO篇

      HashMap:

        底层是哈希表数据结构;实现不同步。允许 null 作为键、null 作为值。替代 HashTable

    HashMap<Integer,String> hm=new HashMap<Integer,String>();
    //若要保证HashMap有序。用LinkedHashMap
    HashMap<Integer,String> hm=new LinkedHashMap<Integer,String>();
    hm.put(1,"元素1");
    hm.put(2,"元素2");
    hm.put(3,"元素3");
    hm.put(4,"元素4");
    
    hm.size();//元素个数
    hm.get(1);//获取键1对应的vaue
    hm.remove(1);//删除键1对应的键值对
    hm.clear();//清空
    hm.containsKey(1);//是否包含键1
    
    //取Map 集合中所有的键值
    Set<Integer> hmKey=hm.keySet();//获取所有的键
    for(Iterator<Integer> iter=hmKey.iterator(); iter.hasNext()){
      Integer it=iter.next();
      hm.get(it);    
    }
    
    //取Map 集合中所有的键值。
    Set<Map.Entry<Integer,String>> hmEntry=hm.entrySet();//获取Map 集合中所有的简直对应关系
    for(Iterator<Map.Entry<Integer,String>> iter=hmEntry.iterator(); iter.hasNext()){
      Map.Entry<Integer,String> me=iter.next();
      Integer key=me.getKey();
      String value=me.getValue();
    }

      TreeMap:

        对Map 集合中的键进行排序。

    /* 自定义集合的两种排序方式 */
    //一、实现Comparable 接口。重写compareTo() 方法。
    TreeMap<Student,String> tm=new TreeMap<Student,String>();
    tm.put(new Student("姓名","年龄"),"Str元素");
    tm.put(new Student("姓名","年龄"),"Str元素");
    tm.put(new Student("姓名","年龄"),"Str元素");
    
    Set<Student> tmkey=tm.keySet();
    for(Iterator<Student> iter=tmkey.iterator(); iter.hasNext()){
      Student stu=iter.next();
      tm.get(stu);
    }
    
    Class Student implements Comparable<Student>{
      /*
        Code...
      */  
      public int compareTo(Student stu){
        int temp=this.age-stu.age;
        return temp==0?this.name.compareTo(stu.name):temp;
      }
    }    
    
    //二、实现Comparator 接口,重写compare() 方法。
    TreeMap<Student,String> tm=new TreeMap<Student,String>(new ComparaByName());
    tm.put(new Student("姓名","年龄"),"Str元素");
    tm.put(new Student("姓名","年龄"),"Str元素");
    tm.put(new Student("姓名","年龄"),"Str元素");
    
    Set<Student> tmkey=tm.keySet();
    for(Iterator<Student> iter=tmkey.iterator(); iter.hasNext()){
      Student stu=iter.next();
      tm.get(stu);
    }
    
    Class ComparaByName implements Comparator<Student>{
      public int compare(Student stu1,Student stu2){
        int temp=stu1.getName().compareTo(stu2.getName());
        return temp==0?new Interger(stu1.getAge()).compareTo(new Integer(stu2.getAge)):temp;
      }
    }

      集合框架工具类:

        Collections、Arrays 这两个工具类中的方法都是静态的,不需要创建对象,直接使用类名调用即可。

        Collections:是集合对象的工具类,提供操作集合的工具方法。

    Collections.sort(List<T>);//排序,升序
    Collections.sort(List<T>,Collections.reverseOrder);//排序,降序
    Collections.sort(List<T>,Collections.reverseOrder(Comparator<? super T>));//指定比较器排序,降序
    Collections.max();//最大值
    Collections.min();//最小值
    Collections.binarySearch();//二分查找(折半查找),只作用于List集合
    Collections.fill(List<T>,"");//将集合中的元素替换成指定元素
    Collections.reverse(List<T>);//将集合元素反转,头尾对调
    Collections.swap(List<T>,int,int);//对集合中元素进行位置替换
    Collections.shuffle(List<T>);//对集合中的元素进行随机位置置换
    Collections.synchronizadList(List<T>);//可以将一个不同步的集合转成同步的List集合。

        Arrays:是数组的工具类。提供操作数组的工具方法。

          Arrays.asList(Array);  数组转成集合

          当数组中的元素是引用类型的数据时,变集合后数组中的元素作为集合中的元素存在。

          当数组中的元素是基本数据类型时,变集合后该数组变成集合中的元素。

          在 Collection 接口中有个集合变数组的方法:toArray();

          ArrayList<String> al=new ArrayList<String>();

          al.toArray(new String[al.size()]);

        jdk1.5版本后,Collection 有个父接口 Iterable 。该接口的出现封装了迭代器 iterator() 方法,并提供了一个增强 for 循环。增强 for 循环只能遍历数组和 Collection 集合。简化迭代器。一般只用于遍历,而不对元素进行操作。

        格式:

          for(元素类型  变量:数组 或 Collection 集合){

            循环体Code;

          }

    ArrayList<String> al=new ArrayList<String>();
    al.add("元素1");
    al.add("元素2");
    al.add("元素3");
    
    for(String str:al){
      System.out.println(s);
    }

        可变参数:

          在指定数据类型的后面加三个点,其实就是数组类型的参数。

          格式:

            void method(int... arr)

          若函数上有多个参数,可变参数的位置必须是最后一个参数。否则编译失败。

        静态导入:

          为简化集合框架工具类 Collections 的书写,导入一个类名中所有的静态成员 import static java.util.Collections.* 然后直接使用sort()、binarySearch() 等方法来简化Collections.sort()等写法。

          但是当方法名称重复时,必须要指定所属的工具类名 Arrays.toString(arr);

  • 相关阅读:
    zend studio 的vim插件
    [转]mysql性能优化慢查询分析、优化索引和配置
    mysql日期函数整理
    系统进行多语言支持转换
    table xxxx is full 报警问题处理
    坚持的力量
    $_SERVER内容的意义
    smarty 注册函数使用初体验
    Mysql输入错误时取消输入
    js:
  • 原文地址:https://www.cnblogs.com/zltao/p/9942882.html
Copyright © 2020-2023  润新知