zoukankan      html  css  js  c++  java
  • Java集合之Collection与之子类回顾

    Java学习这么久,打算这几天回顾下java的基本知识点,首先是集合。

    一、常用集合类关系图

    Collection

      |___List  有序,可重复

        |___ArrayList   底层数据结构是数组,增删慢,查询快;线程不安全,效率高

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

        |___Vector    底层数据结构是数组,增删慢,查询快;线程安全,效率低

      |___Set  无序,不可重复

        |___HashSet

        |___TreeSet

    Map

      |___HashMap

      |___TreeMap

    二、集合两个问题(Why?Feature?)

    1、Why?为什么使用集合?

     java是一种面向对象语言,为了方便对对象的操作,所以使用了集合。

    2、Feature?集合有什么特点?即它和数组的不同点。

    集合:①存储不同引用类型对象 长度可变

    数组:①存储相同数据类型(包括数据类型和引用类型) ②长度不可变

    三、Collection概述

     Collection的功能概述:
     1:添加功能

     boolean add(Object obj):添加一个元素
     boolean addAll(Collection c):添加一个集合的元素

     2:删除功能

     void clear():移除所有元素
     boolean remove(Object o):移除一个元素
     boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有) 注意:只要有一个元素被移除,就返回True

    3:判断功能

     boolean contains(Object o):判断集合中是否包含指定的元素
     boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有) 注意:要包含所有的元素,返回True
     boolean isEmpty():判断集合是否为空

    4:获取功能

     Iterator<E> iterator()(重点) 集合专用迭代器
     1 //创建集合
     2 
     3 Collection c= new ArrayList();
     4 
     5 //集合添加元素
     6 
     7 c.add("Hello");
     8 
     9 c.add("World");
    10 
    11 //使用迭代器
    12 
    13 Iterator it =c.iterator();
    14 
    15 While(it.hasNext ()){
    16 
    17   String s =(String) it.next();
    18 
    19   System.out.println(s);
    20 
    21 }
     1 //迭代器源码
     2 public interface Inteator {
     3     boolean hasNext();
     4     Object next(); 
     5 }
     6 
     7 public interface Iterable {
     8     Iterator iterator();
     9 }
    10 
    11 public interface Collection extends Iterable {
    12     Iterator iterator();
    13 }
    14 
    15 public interface List extends Collection {
    16     Iterator iterator();
    17 }
    18 
    19 public class ArrayList implements List {
    20     public Iterator iterator() {
    21         return new Itr();
    22     }
    23     
    24     private class Itr implements Iterator {
    25         public boolean hasNext() {}
    26         public Object next(){} 
    27     }
    28 }

    5:长度功能

     int size():元素的个数

    面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?

    数组求长度用length属性

    字符串求长度用length()方法

    集合求长度用size()方法

    6:交集功能

     boolean retainAll(Collection c)

    两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?

    假设有两个集合A,B。
    A对B做交集,最终的结果保存在A中,B不变。
    返回值表示的是A是否发生过改变。

    7:把集合转换为数组

      Object[] toArray()

    集合转换成数组例子

     1 //创建集合对象
     2 
     3 Collection c = new ArrayList();
     4 
     5 //添加元素
     6 
     7 c.add("Hello");
     8 
     9 c.add("World");
    10 
    11 //集合转换成数组
    12 
    13 Object[]  obj = c.toArray();
    14 
    15 //遍历集合
    16 
    17 for(int x =0;x<obj.length;x++){
    18 
    19   System.out.println(obj[x]);
    20 
    21 }

    四、Collection下List特有功能

    A:添加功能

    void add(int index,Object element): 在指定位置添加元素

    B:获取功能

    Object get(int index):获取指定位置的元素
     1 //List的特有遍历---普通for 遍历
     2 //创建对象
     3 List list = new ArrayList();
     4 //添加元素
     5 list.add("Hello");
     6 list.add("World");
     7 //普通for遍历
     8 for(int x=0;x<list.size();x++){
     9      String s=(String)list.get(x);
    10      System.out.println(s);
    11 }

    C:列表迭代器

    ListIterator listIterator():List集合特有的迭代器

    D:删除功能

    Object remove(int index):根据索引删除元素,返回被删除的元素

    E:修改功能

    Object set(int index,Object element):根据索引修改元素,返回被修饰的元素

    五、引入泛型

    泛型是将类型明确工作推迟到对象创建或者方法调用的时候。

    泛型的格式:<数据类型>  注意:此处的数据类型只能是引用类型。int----Integer   

    泛型的好处:

    A.将运行期间的错误提前到编译期间

    B.避免强制类型转换

     1 //创建集合对象加入泛型
     2 ArrayList<String> list = new ArrayList<String>()
     3 list.add("Hello");
     4 list.add("World");
     5 //使用迭代器
     6 Iterator<String> it = list.iterator();
     7 While(it.hasNext()){
     8 //使用泛型后不用进行类型强制转换
     9   String s = list.next();
    10   System.out.println(s);
    11 }

    JDK7 新特性:泛型推断。

    ArrayList<Student> array = new ArrayList<>();

    将泛型定义到类上

    public class ObjectTool<T> {
        private T obj;
    
        public T getObj() {
            return obj;
        }
    
        public void setObj(T obj) {
            this.obj = obj;
        }
    }

    将泛型定义到方法上

    public class ObjectTool {
        public <T> void show(T t) {
            System.out.println(t);
        }
    }

    将泛型定义到接口上

    public interface Inter<T> {
        public abstract void show(T t);
    }

    高级通配符

    <?>:任意类型,没有指定就是Object类型
    <? extends E>:向下限定,E及其子类
    <? super E>:向上限定,E及其父类
    class  Animal{}
    class Dog extends Animal{}
    class Cat extends  Animal{}
    
    Collection<?>  c = new ArrayList<Animal>();
    Collection<?>  c =  new ArrayList<Dog>();
    Collection<?>   c= new ArrayList<Cat>();
    
    Collection<? extends Animal> c =new  ArrayList<Animal>();
    Collection<? extends Animal> c =new ArrayList<Dog>();
    Collection<? extends Animal> c = new ArrayList<Cat>();
    
    Collection<? super Animal> c =new ArrayList<Animal>;
    Collection<? super Animal> c = new ArrayList<Object>;

    六、JDK 5 新特性

    增强for遍历集合

    格式:

    for(数据类型  变量名:遍历的集合或数组名){
    
    }

    好处:简化了数组和集合的遍历方式。

    缺点:需要遍历的集合或数组不能为空。

          解决方案:遍历之前做if判断。

    ArrayList<String> list = null;
    if(list!=null){
       for(String s :list){
            System.out.println(s);    
        }      
    }

    至此List有三种遍历方式

    //创建集合对象
    ArrayList<String> list = new ArrayList<String>();
    list.add("Hello");
    list.add("World");
    //第一种:迭代器遍历
    Iterator<String> it =list.iterator();
    While(it.hasNext()){
    String s = list.next();
    System.out.println(s);
    }
    
    //第二种:普通for遍历
    for(int x=0;x<list.size();x++){
    String s = list.get(x);
    System.out.println(s);
    }
    
    //第三种:增强for遍历
    for(String s :list){
    System.out.println(s);
    }

    静态导入

    import static 包名.类名.方法名
    可以直接导入到方法

    注意事项:①方法必须是静态的。②导入时有多个同名的静态方法,使用时必须要加前缀(包名.类名.方法名)

    可变参数

    如果一个方法的参数不固定,那么我们可以使用可变参数。

    格式:

    修饰符  返回值类型  方法名(数据类型...  变量名){  
    
    }
    //注意:这里的...不是省略号
    
    
    例如:设计一个求和方法,传入的参数数量未知
    
    public int sum(int...a){
        int sum =0;
        for(int i :a){
          sum+=i;
    }      
       return sum;
    }

    注意:①这里的变量实际上是一个数组,所以可以使用增强for遍历。

       ②如果一个方法除了可变参数还有别的参数,那么可变参数一定要放到参数的最后。

    数组转集合     

    public static <T> List<T> asList(T... a):把数组转成集合

    List<String> list = Arrays.asList("hello","World","Java");

    注意:虽然数组可以转成集合,但是这个集合的长度不可变,固定

    七、List下ArrayList、Vector、LinkedList特有功能

    //Vector特有功能
    
    //添加功能
    public void addElement(Object obj)     --------add()    
    
    //获取功能
    public Object elementAt(int index)     -------- get()    
    public Enumeration elements()          --------Iterator iterator()
    boolean hasMoreElements()              --------hasNext()
    Object nextElement()                   --------next()
    //LinkedList的特有功能:
    
    //添加功能
    public void addFirst(Object e)
    public void addLast(Object e)
    
    //获取功能
    public Object getFirst()
    public Obejct getLast()
    
    //删除功能
    public Object removeFirst()
    public Object removeLast()

    八、collection下set概述

    set是一个元素无序且唯一的集合

    HashSet:

    HashSet为何存储元素是唯一的呢?

    原因:HashSet底层依靠的是hashCode()和equals()方法。

    先比较hashCode(),如果相同继续比较equals(),equals()返回true说明元素重复,返回false则添加进集合

    HashSet 的add()源码:

    interface Collection {
        ...
    }
    
    interface Set extends Collection {
        ...
    }
    
    class HashSet implements Set {
        private static final Object PRESENT = new Object();
        private transient HashMap<E,Object> map;
        
        public HashSet() {
            map = new HashMap<>();
        }
        
        public boolean add(E e) { //e=hello,world
            return map.put(e, PRESENT)==null;
        }
    }
    
    class HashMap implements Map {
        public V put(K key, V value) { //key=e=hello,world
        
        //看哈希表是否为空,如果空,就开辟空间
            if (table == EMPTY_TABLE) {
                inflateTable(threshold);
            }
            
            //判断对象是否为null
            if (key == null)
                return putForNullKey(value);
    
            //和对象的hashCode()方法相关
            int hash = hash(key); 
            
            //在哈希表中查找hash值
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                //这次的e其实是第一次的world
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    return oldValue;
                    //走这里其实是没有添加元素
                }
            }
    
            modCount++;
            addEntry(hash, key, value, i); //把元素添加
            return null;
        }
        
        transient int hashSeed = 0;
        
        final int hash(Object k) { //k=key=e=hello,
            int h = hashSeed;
            if (0 != h && k instanceof String) {
                return sun.misc.Hashing.stringHash32((String) k);
            }
    
            h ^= k.hashCode(); //这里调用的是对象的hashCode()方法
    
            // This function ensures that hashCodes that differ only by
            // constant multiples at each bit position have a bounded
            // number of collisions (approximately 8 at default load factor).
            h ^= (h >>> 20) ^ (h >>> 12);
            return h ^ (h >>> 7) ^ (h >>> 4);
        }
    }
    
    
    hs.add("hello");
    hs.add("world");
    hs.add("java");
    hs.add("world");

    LinkedHashSet:

    存储元素有序且唯一。

    HashSet保证其存储元素唯一;Linked保证其存储元素有序(输入和输出元素有序)

    TreeSet:

    能够对元素按照某种规律进行排序;

    A 自然排序,如果没有指定,则从小到大排序。

    让元素所属的类实现自然排序接口 Comparable,重写接口中compareTo ()方法。

    B 比较器排序。

    让集合的构造方法接收一个比较器接口的子类对象 Comparator,此时可以使用匿名内部类方法实现排序。

    //实现比较器排序的局部代码
    TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    // 姓名长度
                    int num = s1.getName().length() - s2.getName().length();
                    // 姓名内容
                    int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
                            : num;
                    // 年龄
                    int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
                    return num3;
                }
            });
  • 相关阅读:
    java图片压缩处理
    RocketMQ启动broker提示 错误:找不到或无法加载主类
    Docker
    openresty (nginx+lua)实现请求过滤
    mybatis-3.4.0 Date类型非空字符串判断bug
    ClickHouse 官方文档
    Flume 搭建遇到的问题
    Hadoop与HDFS
    关于Linux
    mybatis insert 返回主键
  • 原文地址:https://www.cnblogs.com/zhoumiao/p/7657286.html
Copyright © 2011-2022 走看看