• 06-java学习笔记-集合框架


    1.集合框架概述

    集合类

    为什么出现类集合?
         面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,
         就对对象进行存储,集合就是存储对象最常用的一 种方式。
    数组和集合类同是容器,有何不同?
         数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
         数组中可以存储基本数据类型,集合只能存储对象
    集合类的特点
         集合只用于存储对象,
         集合长度是可变的,
         集合可以存储不同类型的对象。
    2.集合框架的构成及分类&共性功能
    注:虚线框都是接口
    集合体系的共性内容都在Collection
    Collection 是一个接口
    Collection中的常见方法:
    1.添加
         boolean add(Object obj);
         boolean addAll(Collection coll);
    2.删除
         boolean remove(Object obj);
         boolean removeAll(Collection coll);//删除集合中所有的相同元素
    3.判断
         boolean contains(Object obj);
         boolean containsAll(Collection coll);//集合中是否包含另一个集合的所有元素
         boolean isEmpty();//判断集合中是否有元素
    4.获取
         int size();
         Iterator iterator();//取出元素的方式:迭代器
         该对象必须依赖于具体容器,因为每一个容器的数据的数据结构不同
         所以该迭代器对象是在容器中进行内部实现的
         所以对使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器对象即可
         也就是iterator方法
         Iterator接口就是对所有的Collection容器进行元素取出的公共接口
    5.其他
         boolean reatainAll(Collection coll); //取交集 , 如果有交集返回true
         Object[] toArray();                         //将集合转成数组
    3 迭代器的使用
         迭代是取出集合中元素的一种方式。
         因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。
    方法:
         1. boolean hasNexrt() //如果仍有元素可以迭代,则返回 true。
         2. E next()                   //返回迭代的下一个元素。
         3. void remove()         //从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
      
    用法:
    Collection coll = new ArrayList();
    // 方式1
    Iterator it = l.iterator();
    while(iter.hasNext())
    {
         System.out.println(it.next());
    }
    // 方式2 结束后it 不可用 
    for( Iterator it = iterator(); it.hasNext(); )
    {
         System.out.println(it.next());
    }
    通过内部类实现
    迭代注意事项
    迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。
    迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
    迭代器的next方法返回值类型是Object,所以要记得类型转换。
    思考:为什么next方法的返回类型是Object的呢?
    因为集合中的元素类型是Object
    4 集合框架的两个常用接口List和Set的特点
    集合框架的常用接口
    Collection接口有两个子接口
    List(列表),   Set(集)
    List: 可存放重复元素,元素存取是有序
    Set:不可以存放重复元素,元素存取是无序的。
    5 List
    List接口中常用类
         Vector:线程安全,但速度慢,已被ArrayList替代。
         ArrayList:线程不安全,查询速度快。
         LinkedList:链表结构,增删速度快。
    List特有的常见方法:有一个共性的特点 就是都可以操作角标。
    取出LIst集合中元素的方式:
         1.     get(int index):通过脚标获取元素。
         2.     iterator():通过迭代方法获取迭代器对象。
    1. 添加
              void add(index, element);
              void add(index, collection);
    2. 删除
              Object remove(index);
    3. 修改
              Object set(index, element);
    4. 获取
              Objext get(index);
              int indexOf(object);
              int lastIndexOf(object);
              List subList(from, to);
    List集合是可以完成增删改查的。
    ListIterator接口

         iterator的操作再用集合的操作就会产生异常ConcurrentModificationException
         所以List 接口提供了特殊的迭代器,称为 ListIterator,
         除了允许 Iterator 接口提供的正常操作外,
         该迭代器还允许元素插入和替换,以及双向访问。
         还提供了一个方法来获取从列表中指定位置开始的列表迭代器。
         通过List中的 ListIterator<E> listIterator()方法获取。
                      或者ListIterator<E> listIterator(int index)
         ListIterator 接口中的方法:
         还可以双向遍历 hasPrevious()     previous() 方法
         1. void add(E e) 添加
         2. void remove()
         3. void set(E e)
         
    6 List常用子类

    List:
         |--Vector        内部是数组数据结构,是同步的。增删,查询的速度都很慢
         |--ArrayList     内部是数组数据结构,是不同步的。替代Vector。查询的速度快
         |--LinkedList   内部是链表数据结构,是不同步的。增删元素的速度很快

    7 Set常用子类
    Set接口中常用的类

    Set:无序,不可以有重复元素。
         |--HashSet     线程不安全
                               数据结构是哈希表。线程是非同步的
                               保证元素的唯一性的原理:判断元素的hashCode值是否相同。
                               如果相同,还会继续判断元素的equals方法,是否为true。
         |--TreeSet       线程不安全
                               可以对Set集合中的元素进行排序。
                               底层数据结构是二叉树
                               保证元素唯一性的依据是compareTo方法return 0;
                               TreeSet排序的
                               第一种方式:让元素自身具备比较性
                                       元素需要实现Comparable接口,覆盖compareTo方法
                                       这种方法也称为元素的自然顺序,或者叫做默认顺序
                               第二种方式
                                       当元素自身不具备比较性时,或者具备的比较性不是所需要的
                                       这时就需要让集合自身具备比较性。
                                       在集合初始化时,就有了比较方式。构造函数
    HashSet:线程不安全,存取速度快。
    TreeSet:线程不安全,可以对Set集合中的元素进行排序。
    它的排序是如何进行的呢?
         需要使其中的元素具备比较性
         即实现Comparable接口的int compareTo(T o)方法
    Set集合元素唯一性原因
         HashSet:通过equals方法和hashCode 方法来保证元素的唯一性。
         TreeSet:通过compareTo或者compare 方法中的来保证元素的唯一性。元素是以二叉树的形式存放的。
    存储自定义对象
    TreeSet ts = new TreeSet();
    ts.add(new Student("lisi", 20);
    ts.add(new Student("zhangsan", 21);
    出现类型转换异常 ClassCastException    
    排序时,当主要条件相同时,一定要比较次要条件。
    class Student implements Comparable
    {
         ......
         public int compareTo(Object obj)
         {
              if(!(obj instanceof(Student))
                   throw new RuntimeException("不是学生对象");
              Student s = (Student)obj;
              if(this.age>s.age)
                   return 1;
              else if(this.age == s.obj)
              {
                   return this.name.compareTo(s.name);//String类实现了Comparable接口
              }
              else
                   return -1;
         }
    }
    底层数据结构是二叉树 
    8 实现Comparator方式排序

    当元素自身不具备比较性,或者具备的比较性不是所需要的。
    这时需要让容器自身具备比较性。
    定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

    当两种排序都存在时,以比较器为主。
    定义一个,实现Comparator接口,覆盖compare方法。

    class MyCompare implements Comparator
    {
         public int compare(Object o1, Object o2)
         {
              Student s1 = (Student)o1;
              Student s2 = (Student)o2;
              
              int num = s1.getName().compareTo(s2.getName);
              if(num == 0)
              {
                  new Integer(s1.getAge()).compareTo(new Integer(s2.getAge());
              }
              return num;
         }
    }

    TreeSet ts = new TreeSet(new MyCompare());
    TreeSet练习
         按照字符串长度排序
           字符串本身具备比较性。但是它的比较方式不是所需要的。
           这时就只能使用比较器
    9 泛型
    泛型:JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。

    好处
    1.将运行时期出现问题ClassCastException,转移到了编译时期。,
         方便于程序员解决问题。让运行时问题减少,安全。,
    2,避免了强制转换麻烦
    泛型的特点
    提高了程序的安全性
    将运行期遇到的问题转移到了编译期
    省去了类型强转的麻烦
    泛型类的出现优化了程序设计
    泛型格式:通过<>来定义要操作的引用数据类型。

    在使用java提供的对象时,什么时候写泛型呢?

    通常在集合框架中很常见,
    只要见到<>就要定义泛型。

    其实<> 就是用来接收类型的。
    当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
    例程
    1.
    ArrayList<String> al = new ArrayList<String>();
    Iterator<String> it = al.iterator();

    TreeSet<String> ts = new TreeSet<String>(new LenComparator());

    Iterator<String> it = ts.iterator();

    class LenComparator implements Comparator<String>
    {

    }
    2.
    TreeSet<String> ts = new TreeSet<String>(new LenComparator());
    Iterator<String> it = ts.iterator();

    class LenComparator implements Comparator<String>
    {
         public int compare(String o1,String o2)
         {
              ......
         }
    }
    3 泛型类。
    什么时候定义泛型类?
    当类中要操作的引用数据类型不确定的时候,
    早期定义Object来完成扩展。
    现在定义泛型来完成扩展。
    class Utils<QQ>
    {
         private QQ q;
         public void setObject(QQ q)
         {
              this.q = q;
         }
         public QQ getObject()
         {
              return q;
         }
    }
    class  GenericDemo3
    {
         public static void main(String[] args)
         {
              Utils<Worker> u = new Utils<Worker>();

              u.setObject(new Student());//编译失败
              Worker w = u.getObject();    
         }
    }
    4 泛型方法
    泛型类定义的泛型,在整个类中有效。如果被方法使用,
    那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
    为了让不同方法可以操作不同类型,而且类型还不确定。
    那么可以将泛型定义在方法上。
    特殊之处:
    静态方法不可以访问类上定义的泛型
    如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
    class Demo<T>
    {
         public  void show(T t)
         {
              System.out.println("show:"+t);
         }
         public <Q> void print(Q q)
         {
              System.out.println("print:"+q);
         }
         public  static <W> void method(W t)
         {
              System.out.println("method:"+t);
         }
    }
    5 泛型定义在接口上
    interface Inter<T>
    {
         void show(T t);
    }

    /*
    class InterImpl implements Inter<String>
    {
         public void show(String t)
         {
              System.out.println("show :"+t);
         }
    }

    */
    //实现的时候也不知道类型
    class InterImpl<T> implements Inter<T>
    {
         public void show(T t)
         {
              System.out.println("show :"+t);
         }
    }
    class GenericDemo5
    {
         public static void main(String[] args)
         {

              InterImpl<Integer> i = new InterImpl<Integer>();
              i.show(4);
              //InterImpl i = new InterImpl();
              
    //i.show("haha");
         }
    }
    6.泛型限定
    ? 通配符。也可以理解为占位符。
    泛型的限定;
    ? extends E: 可以接收E类型或者E的子类型。上限。
    ? super E: 可以接收E类型或者E的父类型。下限
    7.应用
    Comparator<E>   
    public TreeSet(Comparator<? super E> comparator)//可以接收E和E的父类

  • 相关阅读:
    android 14 进度条和拖动条
    android 13 5种click事件不同实现方式 比较
    android 12 click事件的不同实现方式
    android 11 模拟onclick 事件
    android 10 事件
    android 09
    android 08 AndroidManifest.xml
    android 07 22 23没看
    Linux常用命令last的使用方法详解
    Linux TOP命令 按内存占用排序和按CPU占用排序
  • 原文地址:https://www.cnblogs.com/chasingw/p/4844640.html
Copyright © 2020-2023  润新知