集合--核心总结

Java集合容器

         1.为什么使用集合:

                     1)动态扩容机制;

                     2)   减少资源浪费;

                     3)   如果我们不知道程序运行时会需要多少对象,或者需要跟复杂的方式存储对象--可以使用Java集合框架;

         2. 集合整体结构:

                    

         3.List与Set:

                   1) Collection接口存储一组不唯一、无序的对象;

                   2) List接口存储一组不唯一、有序的对象;

                   3) Set接口存储一组唯一、无序的对象;

                   4) Map接口存储一组键值对象,提供key映射到value的映射;   

一:Collection接口:

                   1.本质:存放的是单一值,本质还是使用的是一个Object类型的数组;

                    

                   2.特点:1)可以存放不同类型的数据,而数组只能存放固定类型的数据;  

                                 2)当使用arrayList子类实现的时候,初始化长度是10,当长度不够时会进行自动扩容操作();

                                     

                                 3)扩容机制:原来旧的长度+旧长度的/2 新长度为旧长度的1.5倍;

                                       

                                 4)常用API方法:

                                       a)添加数据的方法:

                                                    add():要求必须传入的参数是Object对象类型,因此当写入基本类型时,包含自动拆箱和自动装箱的过程;

                                                   addAll():添加另一个集合的元素到此集合中;

                                      b) 删除数据的方法:

                                                   clear(): 只是清空集合中的元素,但是此集合对象并没有被回收;

                                                   remove(): 删除集合中特定的元素;

                                                   removeAll(): 删除集合中集合元素;

                                      c)查询数据的方法:

                                                  contains(): 判断集合中是否包含指定的元素;

                                                  containsAll():判断此集合中是否包含另一个集合;

                                                  retainAll(): 若集合中拥有另一个集合的所有元素,返回true,否则返回false  

                                                  size(): 返回当前集合的大小

                                                 isEmpty(): 判断此集合是否为空;

                                     d)转数组操作:

                                                 toArray(): 将集合装换为数组

                                    代码实现:

package com.cy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * java集合框架:
 *       Collection:存放的是单一值,本质还是使用的是一个Object类型的数组;
 *       特点:
 *           1.可以存放不同类型的数据,而数组只能存放固定类型的数据;
 *           2.当使用arrayList子类实现的时候,初始化长度是10,当长度不够时会进行自动扩容操作();
 *           3.扩容机制:原来旧的长度+旧长度的/2 新长度为旧长度的1.5倍;
 *
 *
 *       API方法;
 *           添加数据的方法:
 *           add():要求必须传入的参数是Object对象类型,因此当写入基本类型时,包含自动拆箱和自动装箱的过程;
 *           addAll():添加另一个集合的元素到此集合中;
 *           删除数据的方法:
 *           clear(): 只是清空集合中的元素,但是此集合对象并没有被回收;
 *           remove(): 删除集合中特定的元素;
 *           removeAll(): 删除集合中集合元素;
 *           查询数据的方法:
 *           contains(): 判断集合中是否包含指定的元素;
 *           containsAll():判断此集合中是否包含另一个集合;
 *           retainAll(): 若集合中拥有另一个集合的所有元素,返回true,否则返回false
 *           size(): 返回当前集合的大小
 *           isEmpty(): 判断此集合是否为空;
 *
 *           转数组操作:
 *           toArray(): 将集合装换为数组
 *
 */
public class CollectionDemo {
    public static void main(String[] args) {
        Collection collection=new ArrayList();
        //在集合中添加元素
        collection.add(1);
        collection.add(true);
        collection.add(1.21);
        collection.add("abc");
        System.out.println(collection);
        //集合中在特定下标添加元素
        ((ArrayList) collection).add(0,"老王");
        System.out.println(collection);

        Collection collection1=new ArrayList();
        collection1.add("a");
        collection1.add("b");
        collection1.add("c");
        collection1.add("d");

        //添加另一个集合元素
        collection.addAll(collection1);
        //判断集合中是否包含指定的元素
        System.out.println(collection.contains("a"));
        //判断该集合中是否包含另一个集合
        System.out.println( collection.containsAll(collection1));
        //判断该集合是否为空
        System.out.println(collection.isEmpty());
        //判断删除某一个特点的元素
        collection.remove("a");
        //删除集合元素
        collection.removeAll(collection1);
        //判断一个集合是否包含另一个集合的所有元素
        collection.retainAll(collection1);
        //集合转数组
        Object[] objects = collection.toArray();

        //清空集合元素
        collection.clear();
        System.out.println(collection);

    }
}

    二:List接口: 

                          特点:有序,不唯一(可以重复)

                   实现类一:ArrayList

                                 1)ArrayList: 实现了长度可变的数组,在内存中分配连续的空间;

                                            

                                       

                                        优点:遍历元素和随机访问元素的效率比较高;

                                        缺点:添加、删除需要大量移动元素效率低,按照内容查询效率低;

                   实现类二:LinkedList

                                 2)LinkdeList: 采用链表存储方式;

                                        

                                         

                                       

                                       优点:  插入、删除元素时效率比较高;

                                        缺点:遍历和随机访问元素效率低下;

                          常用API:

                                        a) 添加数据的方法:

                                                  add():要求必须传入的参数是Object对象类型,因此当写入基本类型时,包含自动拆箱和自动装箱的过程;

                                                 addAll():添加另一个集合的元素到此集合中;

                                                 set():在集合中指定的位置添加指定的值;

                                        b) 删除数据的方法:

                                                 clear(): 只是清空集合中的元素,但是此集合对象并没有被回收;

                                                 remove(): 删除集合中特定的元素;

                                                 removeAll(): 删除集合中集合元素;

                                       c)查询数据的方法:

                                                getIndex(): 获取指定的下标元素;

                                                indexOf(): 返回指定元素的下标;(向后找)

                                                lastIndexOf(): 返回指定元素的下表 (向前找)

                                               contains(): 判断集合中是否包含指定的元素;

                                               containsAll():判断此集合中是否包含另一个集合;

                                               retainAll(): 若集合中拥有另一个集合的所有元素,返回true,否则返回false

                                               size(): 返回当前集合的大小

                                               isEmpty(): 判断此集合是否为空;

                                               subList(): 截取集合中指定内容的集合;

                                       b) 转数组操作:

                                               toArray(): 将集合装换为数组

package com.cy;

import java.util.ArrayList;
import java.util.List;

/**
 * java集合框架:
 *       List:存放的是单一值,本质还是使用的是一个Object类型的数组;
 *       特点:
 *           1.可以存放不同类型的数据,而数组只能存放固定类型的数据;
 *           2.当使用arrayList子类实现的时候,初始化长度是10,当长度不够时会进行自动扩容操作();
 *           3.扩容机制:原来旧的长度+旧长度的/2 新长度为旧长度的1.5倍;
 *
 *
 *       API方法;
 *           添加数据的方法:
 *           add():要求必须传入的参数是Object对象类型,因此当写入基本类型时,包含自动拆箱和自动装箱的过程;
 *           addAll():添加另一个集合的元素到此集合中;
 *           set():在集合中指定的位置添加指定的值;
 *           删除数据的方法:
 *           clear(): 只是清空集合中的元素,但是此集合对象并没有被回收;
 *           remove(): 删除集合中特定的元素;
 *           removeAll(): 删除集合中集合元素;
 *           查询数据的方法:
 *           getIndex(): 获取指定的下标元素;
 *           contains(): 判断集合中是否包含指定的元素;
 *           containsAll():判断此集合中是否包含另一个集合;
 *           retainAll(): 若集合中拥有另一个集合的所有元素,返回true,否则返回false
 *           size(): 返回当前集合的大小
 *           isEmpty(): 判断此集合是否为空;
 *           indexOf(): 返回指定元素的下标;(向后找)
 *           lastIndexOf(): 返回指定元素的下表 (向前找)
 *           subList(): 截取集合中指定内容的集合;
 *           转数组操作:
 *           toArray(): 将集合装换为数组
 *
 */
public class ListDemo {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("a");
        list.add(1);
        list.add("a");
        list.add(true);
        System.out.println(list);
        //获取指定下标元素
        System.out.println(list.get(0));
        //返回当前指定元素的下标-->向前找
        System.out.println(list.indexOf("a"));
        //返回当前指定元素的下标-->向后找
        System.out.println(list.lastIndexOf("a"));
        //在当前集合中插入指定元素
        list.set(0,"老王");
        System.out.println(list);
        //list中的截取方法
        List list1 = list.subList(0, 3);
        System.out.println(list1);


    }





}
package com.cy;

import java.util.LinkedList;

/**
 * linkList拥有更加丰富的方法实现,需要用时查询API即可,不需要记忆;
 */
public class LinkedListDemo {

    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
        linkedList.add(123);
        linkedList.add(false);
        linkedList.add("abc");
        System.out.println(linkedList);
        //在指定位置添加节点元素
        linkedList.add(0,"老王");
        //在该集合中首个位置添加节点元素
        linkedList.addFirst("1111");
        //在该集合中最后一个位置添加节点元素
        linkedList.addLast("2222");
        System.out.println(linkedList);
        //获取集合中第一个元素、
        System.out.println(linkedList.element());
        //最后一个节点添加元素
        linkedList.offer("3333");
    }
}

                     Vector:

                                     1) Vector也是List接口的一个子类实现

                                     2) Vector跟ArrayList一样,底层都是使用数据进行实现的

                                     3) Vector跟ArrayList区别:  

                                                     a)ArrayList是线程不安全的,效率高;Vector是线程安全的,效率低;  

                                                     b)ArrayList在进行扩容时,是扩容1.5,Vector扩容时扩容原来的2倍;

package com.cy;

import java.util.Vector;
/**
 *   1.Vector也是List接口的一个子类实现
 *   2.Vector跟ArrayList一样,底层都是使用数据进行实现的
 *   3.Vector跟ArrayList区别:
 *      1)ArrayList是线程不安全的,效率高;Vector是线程安全的,效率低;
 *      2)ArrayList在进行扩容时,是扩容1.5,Vector扩容时扩容原来的2倍;
 */
public class VectorDemo {
    public static void main(String[] args) {
        Vector vector = new Vector();
        vector.add("abc");
        vector.add(1);
        vector.add(false);
        System.out.println(vector);

    }
}

                     Iteractor(迭代器):

                                         Java代码中包含三种循环的方式 : 1)do-while;  2) while;  3)for;

                                                           还有一种增强for循环的方式,可以简化循环的编写;

                                         所有集合都默认实现了Iterable接口,实现此接口意味着具备了增强for循环的能力,也就是for-each;

                                         

                                        增强for循环本质上也是使用的也是iterator的功能;

                                                         方法:  iterator();   foreach();

                                         

                                       

                                        在iterator的方法中,要求返回一个Iterator的接口子类实例对象

                                        此接口也包含了 

                                                       hasNext(); 判断下一个是否有值;

                                                       next(); 返回下一个值;

                                       实现原理:

                                                     

                             注意:在使用iterator进行迭代的过程中如果删除其中某个元素会报错,并发操作异常,因此如果遍历的同时需要修改元素,建议使用listIterator();

                                        ListIterator迭代器提供了向前向后两种遍历的方式:  始终是通过cursor和lastret的指针来获取元素值及向下的遍历索引;

                                                                                                                           当使用向前遍历的时候必须要保证指针在迭代器的结果,否则无法获取结果;

    三:Set接口:

                            1.特点: 1)set中存放的是无序、唯一的数据;

                                          2)由于set无序,所以set不可以通过对应位置的元素值;

                                         3) 使用treeset底层实现是treemap,利用红黑树进行实现;

                            2.实现类:HashSet、TreeSet;

                    HashSet:

                                    1)采用Hashtable哈希表存储结构;本质:底层实现是HashMap;

                                       

                                     

                                       优点:添加、查询、删除速度快;

                                        缺点:无序;

                                        原理:

                                                

                                    2) LinkedHashSet:

                                       采用哈希表存储结构,同时使用链表维护次序;

                                       有序;

                   TreeSet:

                                    采用二叉树(红黑树)的存储结构;                                 

                                         优点:有序(排序后升序)查询速度比list快;

                                          缺点:查询速度没有HashSet快;

                          扩展红黑树:

                                            

                                     

                                代码实现:

package com.cy;

import com.entity.Person;

import java.util.*;

/**
 * 1.set中存放的是无序、唯一的数据;
 * 2.由于set无序,所以set不可以通过对应位置的元素值;
 * 3.使用treeset底层实现是treemap,利用红黑树进行实现;
 * 4.设置元素的时候,如果是自定义对象,会查找对象中equal和hashcode的方法,如果没有,比较的就是地址值;
 * 5.树中的元素是要默认进行排序操作的,如果是基本数据类型,自动比较,如果是引用类型的话,需要自定义比较器;
 *   比较器:
 *     内部比较器:
 *         定义在元素的类中,通过实现comparable接口来进行实现;
 *     外部比较器:
 *         定义在当前类中,通过实现comparator接口来实现,但是要将该比较器传递到集合中;
 *    注意:外部比较器可以定义成一个工具类,此时所有需要比较规则如果一致的话,可以直接复用;
 *         内部比较器只有在存储当前对象的时候才可以使用;
 *         如果两者同时存在,使用外部比较器(当使用比较器的时候不会调用equals)
 */
public class SetDemo implements Comparator<Person> {

    public static void main(String[] args) {
        Set set=new HashSet();
        set.add("abc");
        set.add(123);
        set.add("true");
        set.add("123");
        System.out.println(set);

        //迭代器
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("_______________");
        //将while循环改写成for循环,推荐使用
        for (Iterator iter=set.iterator(); iter.hasNext();){
            System.out.println(iter.next());
        }

        TreeSet treeSet = new TreeSet();
        treeSet.add(34);
        treeSet.add(1);
        treeSet.add(65);
        System.out.println( treeSet.ceiling(0));
        System.out.println(treeSet);


        TreeSet treeSet1 = new TreeSet(new SetDemo());
        treeSet1.add(new Person("zhangsan",14));
        treeSet1.add(new Person("lisi",13));
        treeSet1.add(new Person("wangwu",15));
        treeSet1.add(new Person("zhouliu",16));
        System.out.println(treeSet1);

    }

    /**
     * 根据年龄进行排序
     * @param o1
     * @param o2
     * @return
     */
    @Override
    public int compare(Person o1, Person o2) {
        if (o1.getAge()> o2.getAge()){
            return 1;
        }else if(o1.getAge() < o2.getAge()){
            return -1;
        }else{
            return 0;
        }
    }
}
package com.entity;

import java.util.Objects;

public class Person implements Comparable{
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    /**
     * 次比较器按照name长度比较
     * @param o
     * @return
     */
    @Override
    public int compareTo(Object o) {
        Person person=(Person) o;
        if (person.name.length()> this.name.length()){
            return 1;
        }else if (person.name.length()< this.name.length()){
            return -1;
        }else {
            return 0;
        }
    }
}

          问题: HashSet是如何保证元素的唯一性?

                                通过元素的两个方法,hashCode和equals方法来完成,如果元素的HashCode值相同,才会判断equals方法是否true;如果元素的HashCode值不同,不会调用equals方法;          

      四:Map接口:

                                1. 特点:key-value映射;

                                

                                     

                                2.实现子类:

                                        1)HashMap: 数组+链表(1.7) 数组+链表+红黑叔(1.8)

                                        2) LinkedHashMap: 链表

                                       3) TreeMap: 红黑树

                               3. 常用API:

                                     添加:

                                             put(K,v) 添加元素

                                    查找:  

                                             isEmpty() 判断是否为空

                                             size() 返回map的大小

                                             containKay() 判断是否包含指定的key

                                             cintainValue() 判断是否包含指定的Value值

                                             get() 通过Key获取指定元素

                                            keySet() 获取所有的key值

                                    删除:

                                           clear() 清空结合中的所有元素;

                                           remove() 删除指定元素;

                                  Map.entry:表示K-V组合的一组映射关系,key和value成组出现;

                              代码实现:

public class MapDemo {
    public static void main(String[] args) {

        Map<String,Integer> map=new HashMap<>();
        //向map集合中添加数据
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);
        System.out.println(map);
        //判断当前map是否为空
        System.out.println(map.isEmpty());
        //返回当前集合的大小
        System.out.println(map.size());
        //判断是否包含指定的key
        System.out.println(map.containsKey("a"));
        //判断是否包含指定的Value值
        System.out.println(map.containsValue(2));
        //通过Key获取指定元素
        System.out.println(map.get("a"));
        //根据key删除指定元素
        System.out.println(map.get("a"));
        //清空所有元素
        //map.clear();

        //遍历操作
        //获取所有的Key
        Set<String> keys = map.keySet();
        for (String key:keys) {
            System.out.print("Key:"+key+",Value:"+map.get(key)+" ");
        }
        System.out.println();
        //获取所有的Value值(但只能获取Value,不能获取key)
        Collection<Integer> values = map.values();
        for (Integer value: values) {
            System.out.print(value);
        }

        System.out.println();
        //迭代器
        //通过迭代key,来获取值;
        Set<String> keySet = map.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()){
            String key = iterator.next();
            System.out.print(key+"="+map.get(key));
        }

        System.out.println();
        //map.entry()
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator();
        while (iterator1.hasNext()){
            Map.Entry<String, Integer> next = iterator1.next();
            System.out.print(next.getKey()+"=="+next.getValue());
        }

    }
}

                       常用类一:HashMap: 

                                 1)特点:key无序,唯一(set)

                                              value 无序 不唯一(Collection)

                                 2)hashMap和hashTable的区别:

                                                   a)hashMap线程不安全,效率比较高,hashTable线程线程安全,效率低;

                                                    

                                                   b)hashMap中key和Value都可以为空,hashTable不允许为空;

                                                     

                                                  c) hashMap的初始长度为16,hashTable的初始长度为11;(加载因子均为0.75)

                                                    

                                                      

                                                       

                              3) hashMap初始值为2的N次幂:

                                                    方便进行 &运算操作,提高效率,且&运算要比取模运算效率要高;

                                                    位置计算:hash(hash值) & (initCapacity-1) 哈希值 & (数组初始长度-1);

                              4) hashMap扩容机制:

                                                  1)数组初始长度默认值为16,当填入的数长度大于数组长度*加载因子0.75的长度时,那么新数组长度=原数组长度*2;

                                                  2)在扩容之后涉及到元素迁移过程,迁移的时候只需要判断二进制的前一位是0或者是1,如果是0表示新数组和旧数组的下标位置不变,如果是1,只需将索引位置加上旧数组的长度值即为新数组的下标

                             5)JDK1.7--HashMap.put()执行流程:

                              

                               6) JDK1.8HashMap.put()执行流程:

                               

                             链表使用头插法插入值:

                             

                             7) JDK1.8以后引入红黑树,当阈值(链表长度)大于8,采用红黑树算法

                                                          

                                                     

                              LinkedHashMap: 链表

                                --- 有序的HashMap 速度快;

                               TreeMap:红黑树

                               ----有序 速度没有Hash快;

                               问题:Set与Map有关系吗?

                               采用了相同的数据结构,只用于map的key存储数据结构是map;

     五:Collections工具类

                          1.Collections和Collection区别:前者是集合操作类,后者是集合接口;

                          2.常用API:

                            1)添加:

                              addAll():批量加入元素的方法;

                            2)排序:

                              sort(List<E>,Comparator<E>): 按自定义条件比较;

                              sort(List<E>): 默认按字母顺序排序;

                            3)查询:

                              binarySearch(List<E>): 二分查找

                               注意:二分查找时需要先进行排序操作,如果没有排序时无发找到指定元素;

                            4)批量替换:

                             fil(): 把原来所有元素填充为指定元素;

                           5)数组和集合之间的转化:

                             数组转集合:asList(Array arr);

                             集合转数组:toArray();

                      3.代码实现:

 public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        list.add("af");
        list.add("bg");
        list.add("cssf");
        list.add("dfsghkj");
        //批量加入元素
        Collections.addAll(list,"edkl","fdihcco","grho");
        System.out.println(list);

        //自定义比较器
        Collections.sort(list,new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if (o1.length()>o2.length()){
                    return 1;
                }else if (o1.length()<o2.length()){
                    return -1;
                }else {
                    return 0;
                }
            }
        });
        System.out.println(list);

        //默认按字母顺序排序
        Collections.sort(list);
        System.out.println(list);

        //二分查找
        System.out.println(Collections.binarySearch(list,"af"));
        //批量替换
        Collections.fill(list,"老王");
        System.out.println(list);
     //数组转集合
        int[] arr=new int[]{1,2,3,4,5};
        List<int[]> ints = Arrays.asList(arr);

        //集合转数组
        Object[] objects = ints.toArray();
    }
}

         六:总结

                    1.集合数据结构总结:

                                             

                    2.集合特性总结:

                                  

                     3.面试题总结:

                                 1)集合与数组的区别:

                                       a)  存放对象不同:数组可以存放基本数据类型和对象,集合只可以存放对象;

                                       b)是否支持动态扩容:数组一但创建不能改变,无法动态扩容,集合可以动态扩容;

                                       c)   数据结构不同:数组仅采用了顺序表达方式,而集合采用了顺序表、链表、哈希表、二叉树等数据据结构;

                                       d)   是否知道元素的个数; 数组采用length()来判断,只能告诉数组的容量,而集合size()可以确切知道元素的个数;

                                2) ArrayList和LinkedList的联系和区别:

                                       a)  ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素效率比较高。

                                             

                                      b)  LinkedList采用链表存储方式。插入、删除元素效率比较高

                                            

                               3)  Vector和ArrayList的联系和区别:

                                      联系:实现原理相同,功能相同,都是长度可变的数组结构,很多时候可以互用
                                      区别:
                                               ▪ Vector是早期的JDK接口,ArrayList是替代Vector的新接口
                                               ▪ Vector线程安全,ArrayList重速度轻安全,线程非安全
                                               ▪ 长度需要增长时,Vector默认增长一倍,ArrayList增长50% (1.5+1)

                               4)HashMap和Hashtable的联系和区别

                                      联系:实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用
                                      区别:
                                                ▪ Hashtable是早期的JDK提供的接口,HashMap是新版的JDK提供的接口
                                                ▪ Hashtable继承Dictionary类,HashMap实现Map接口
                                                ▪ Hashtable是线程安全,HashMap线程非安全
                                                ▪ Hashtable不允许null值,HashMap允许null值    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值