zoukankan      html  css  js  c++  java
  • 集合

    集合框架

    什么是集合:

      集合是Java提供的一种容器,用于存放引用类型的数据。

    集合和数组的区别;

      数组是一种长度不可变的容器,用于存放基本数据类型和引用数据类型。

      集合是一种长度可变的容器,它的实现类多种多样,然后列举图中的实现类的特点 ;只能存放引用数据类型,如果想要存放基本数据类型,必须转化成其对应的包装类才能存放。

    怎么学习集合 ,要从上往下学习

      先学习Collection中的方法

        boolean add(E e)       添加元素
        boolean remove(Object o)   删除元素
        void clear()            清空元素,删除所有
        boolean contains(Object o)    是否包含某个元素
        boolean isEmpty()
        int size()

     1 import java.util.ArrayList;
     2 import java.util.Collection;
     3 
     4 public class MyCollection_Test {
     5 
     6     public static void main(String[] args) {
     7         // 多态,调用的是父类自己的方法,但是父类是接口,调用的是实现类类实现了的方法,但是不能调用实现类特有的
     8         Collection<Student> lists = new ArrayList<>();
     9         lists.add(new Student("张三"));
    10         lists.add(new Student("李四"));
    11         lists.add(new Student("王五"));
    12         // 这样是移除不了的,除非重写equals方法,因为重新new了一个对象,地址是不同的;或者在存放是用一个学生变量接收,这样在删除时就好操作了
    13         System.out.println(lists.remove(new Student("张三"))); //执行结果是false
    14     }
    15 }
    16 
    17 class Student {
    18     private String name;
    19 
    20     public Student(String name) {
    21         super();
    22         this.name = name;
    23     }
    24 
    25 }

     Java集合框架的集合类,我们有时候称之为容器。容器的种类有很多种,比如ArrayList、LinkedList、HashSet...,每种容器都有自己的特点,ArrayList底层维护的是一个数组;LinkedList是链表结构的;HashSet依赖的是哈希表,每种容器都有自己特有的数据结构。

      因为容器的内部结构不同,很多时候可能不知道该怎样去遍历一个容器中的元素。所以为了使对容器内元素的操作更为简单,Java引入了迭代器模式! 

      把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构。

        1.迭代器Iterator接口的实现方式

          在JDK中它是这样定义的:对Collection进行迭代的迭代器。迭代器取代了Java Collection Framework中的Enumeration。迭代器与枚举有两点不同:

            1. 迭代器在迭代期间可以从集合中移除元素。

            2. 方法名得到了改进,Enumeration的方法名称都比较长。

              其接口定义如下:

    1 package java.util;
    2 public interface Iterator<E> {
    3     boolean hasNext();//判断是否存在下一个对象元素
    4 
    5     E next();//获取下一个元素
    6 
    7     void remove();//移除元素
    8 }

      2.Iterable

      Java中还提供了一个Iterable接口,Iterable接口实现后的功能是‘返回’一个迭代器,我们常用的实现了该接口的子接口有:Collection<E>、List<E>、Set<E>等。该接口的iterator()方法返回一个标准的Iterator实现。实现Iterable接口允许对象成为For…each语句的目标。就可以通过for…each语句来遍历你的底层序列。

      Iterable接口包含一个能产生Iterator对象的方法,并且Iterable被for…each用来在序列中移动。因此如果创建了实现Iterable接口的类,都可以将它用于for…each中。

    Iterable接口的具体实现:

    Package java.lang;
    
    import java.util.Iterator;
    public interface Iterable<T> {
        Iterator<T> iterator();
    }

      遍历方法:

      第一种:(基本原理)

        第一步:实现迭代器   

    1     Iterator it= lists.iterator();

        第二步:使用while循环 while(it.hasNext()){ sysout( it.next()); }

      第二种:(实质还是第一种)

        不用实现迭代器,直接使用for…each输出

    再学习它的子类List接口

     list有类似于数组的操作

      ArrayList---底层是数组
      LinkedList---底层是链表

      Vector--- 底层是数组(现在不怎么被使用,作为了解)
      void add(int index,E element) 添加元素到指定的下标位置
      E remove(int index) 删除指定下标位置的元素(注意这个和父类的移除不一样,这里可以返回自己移除的元素,有一个后悔的机会)
      E get(int index) 获取指定下标位置的元素
      E set(int index,E element) 修改指定下标位置的元素
      ListIterator listIterator() Iterator的增强版 (增强版的迭代器,可以倒序遍历,但是迭代器的指针必须是在最后一个的位置上,否则不可以使用倒序输出,调用方法是 对象名.下面两个方法 
      boolean hasPrevious()
      E previous()

      

      ArrayList:
        底层就是数组:查询快,增删慢
        线程不安全,效率高

      Vector:
        底层就是数组:查询快,增删慢
        线程安全,效率低
        确实需要使用线程安全的ArrayList,也不建议使用,一般使用Collections类的方法

      LinkedList
        底层数据结构是链表,查询慢,增删快
        线程不安全,效率高

    面试常考题:

      List的选择:   

    首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList、Vector和LinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:

      1. ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
      2. Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
      3. LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
      4. vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
      5. 如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度
        的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。

      6. 如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而
        如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用Linkedlist,因为它移动一个指定位置的数据
        所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
        ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,
        都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,
        Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差
        ,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!

      7. 笼统来说:LinkedList:增删改快
                       ArrayList:查询快(有索引的存在)

    再学习Collection接口的另一个子接口Set

    Set接口的实现类

        hashSet的特点:无序且元素不重复,无序指的是添加的顺序和内存中存储的顺序是不一样的,元素不重复指的是元素在栈内存中的地址不重复,在调用add()方法时,内部调用了没有重写的hashCode和equals方法,所以如果是引用类型,就要重写这两个方法。

        hashSet底层的add()方法是调用了Map接口的put(K key,V vaule)方法,key就是HashSet类型的元素,

     public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }

         

        

      

  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/19322li/p/10673963.html
Copyright © 2011-2022 走看看