2021-01-12 Java 集合的学习总结

/**
 * 一,集合框架的概述:
 * 1,集合数组都是对多个数据进行存储,简称java容器
 * 说明:此时的存储是作用与内存层面上的,不涉及持久化的存储(txt,jpg,avi,数据库,硬盘等等)
 * 2.1,数组在存储多个数据的特点:
 * >初始化时,数组长度需要确定
 * >数组一旦定义好,其元素就确定了,我们只能操作已经确定了的元素数据
 * 2.2,数组在存储多个数据的缺点:
 * >一旦初始化后就确定了长度,不可修改
 * >数组中提供的方法非常有限,对于添加,删除,插入数据等操作,非常的不便。并且效率不高
 * >获取数组中实际元素的个数的需求,数组没有现成的属性或方法
 * >数组存储数据的特点:有序,可重复,对于无序,不可重复的需求,不能满足
 * 二,集合框架
 * -- collection接口:单列集合,用来存储一个个的对象
 *          ---List接口:存储有序的,可重复的数据 ---》"动态"对象
 *                  ----ArrayList,LinkedList,vector
 * ---Set接口:存储无序的,不可重复的数据 ---》数学中的集合
 * ----HashSet,LinkedHashSet,TreeSet
 * -- Map接口:双列集合,用来存储一对(key---value)一对的数据
 * ----HashTable,HashMap,TreeMap,LinkedHashMap,Properties
 *
 * @author rieson
 * @create 2021-01-10-11:34
 */
public class CollectionTest {
    @Test
    public void test1() {

        Collection con = new ArrayList<>();
        //add(Object e):将元素e添加到集合con中
        con.add(1);
        con.add("asd");
        con.add(new Date());

        //size():获取添加的元素的个数
        System.out.println(con.size());

        //addAll():将con1中的元素全部添加到当前几何中
        Collection con1 = new ArrayList<>();
        con1.add(1);
        con1.add(2);
        con.addAll(con1);
        System.out.println(con.size());
        //clear():清空集合中的元素
        //con.clear();
        //isEmpty():判断当前集合是否为空
        System.out.println(con.isEmpty());
        //contains(Object o):判断当前集合中是否包含o
        //我们在判断时,会调用o中对象所在类的equals()方法
        //向Collection接口实现类的对象中添加o时,要求o所在的类要重写equals()方法
        boolean asd = con.contains("asd");
        System.out.println(asd);
        System.out.println(con.contains(new Date()));
        //containsAll:判断集合con1中当前集合中是否全部包含,全部包含返回true,反而为false
        con.containsAll(con1);

    }

    @Test
    public void test2() {
        Collection con = new ArrayList<>();
        //add(Object e):将元素e添加到集合con中
        con.add(1);
        con.add("asd");
        con.add(new Date());
        con.add(false);

        //remove(Object o):删除集合中对应的元素
        con.remove(1);
        //removeAll(Collection con1):删除con与con1中的相同的数据
        Collection con1 = new ArrayList<>();

        con1.add(1);
        con1.add(true);
        con.removeAll(con1);
        System.out.println(con1);
        System.out.println(con);
    }

    @Test
    public void test3() {
        Collection con = new ArrayList<>();

        con.add(1);
        con.add("asd");
        con.add(new Date());
        con.add(false);

        //retainAll(Collection con1):获取当前集合与con集合的交集,并返回给当前集合
//        Collection con1 = Arrays.asList(1,1234);
//        con.retainAll(con1);
//        System.out.println(con);
        Collection con1 = new ArrayList<>();

        con1.add(1);
        con1.add("asd");
        con1.add(new Date());
        con1.add(false);
        //equals(Object o):比较两个集合里面的元素是否相等

        System.out.println(con.equals(con1));
    }
    @Test
    public void test4(){
        Collection con = new ArrayList<>();

        con.add(1);
        con.add("asd");
        con.add(new Date());
        con.add(false);
        //hashCode():返回当前对象的hash值
        System.out.println(con.hashCode());
        //toArray():集合转换成数组
        Object[] objects = con.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
        //数组转换成集合
        List<String> strings = Arrays.asList(new String[]{"aa", "bb", "CC"});
        System.out.println(strings);

        //iterator():返回Iterator接口的实例,用于遍历集合元素,放在IteratorTest.java中测试
    }
    
}


/**
 * 一,集合框架
 * -- collection接口:单列集合,用来存储一个个的对象
 *    ---List接口:存储有序的,可重复的数据 ---》"动态"对象
 *       ---ArrayList:作为List的主要实现类,线程是不安全的,效率高;底层使用的是Object[]存储
 *       ---LinkedList:对于频繁的插入,删除操作时,使用此效率要比Arraylist高;底层使用双向链表存储,
 *       ---vector:作为List的古老实现类,线程是安全的,效率相对低;底层使用的是Object[]存储
 *
 * 2,ArrayList的源码分析:
 * 2.1 jdk1.7情况下
 *       ArrayList list = new ArrayList();底层创建了长度是10的object[]数组elementData
 *       list.add(123);elementData[0] = new Integer(123);
 *       ....
 *       list(123456);如果此次的添加导致底层elementData数组容量不足,则扩容。
 *       默认情况下,扩容为原容量的1.5倍,同时需要将原数组中的数据复制到新的数组中。
 *       结论:建议开发中使用带参数的构造器:ArrayList list = new ArrayList(int capacity)
 * 2.2 jdk1.8中的变化:
 *     ArrayList list = new ArrayList();底层Object[] elementData初始化为{},并没有创建长度为10的数组
 *     list.add(123);第一次调用add()方法时,底层才创建了长度为10的数组,并将数据123,添加到elementData数组中
 *     后续的添加跟扩容跟1.7无异
 * 2.3 小结:jdk7中的ArrayList的对象的创建类似于单例模式的饿汉式,
 *      而jdk8时使用的是饿汉式,延迟了创建数组,节省内存
 *
 * 3,LinkedList源码分析:
 *      LinkedList list = new LinkedList();内部声明了Node类型的first和last属性,默认值为null
 *      list.add(123);将123封装带Node中,创建了Node对象。
 *      其中,Node定义为:体现了LinkedList 的双向链表说法
 *
 *
 *
 *
 *
 *
 *
 * @author rieson
 * @create 2021-01-10-17:41
 */
public class ListTest {
   // 4,List接口中的常用方法

    @Test
    public void test3(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(465);
        list.add("asd");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        for( Object o : list){
            System.out.println(o);
        }
    }
    @Test
   public void test2() {

       ArrayList list = new ArrayList();
       list.add(123);
       list.add(465);
       list.add("asd");
       list.add(new String("hello"));
       list.add(123);
       System.out.println(list);
       //int indexOf(Object obj):返回obj首次出现的位置
        System.out.println(list.indexOf(123));
       //int lastIndexOf(Object obj):返回obj首次出现的位置
        System.out.println(list.lastIndexOf(123));
        // Object remove(int index):移除指定index位置的元素,并返回此元素
         System.out.println(list.remove(2));
         //Object set(int index,object obj ):修改指定index位置的元素为obj
        System.out.println(list.set(1,"asd"));
        //List subList(int fromIndex,int toIndex):返回fromIndex到toIndex位置的左臂右开区间的值
        List list1 = list.subList(2, 4);
        System.out.println(list1);


    }


    @Test
    public void test1(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(465);
        list.add("asd");
        list.add(new String("hello"));
        list.add(123);
        System.out.println(list);
        //void add(int index,Object ele):在index位置插入 ele元素
        list.add(2,"qwe");
        //boolean addAll(int index,Collection clo):从index位置开始给clo元素全部添加到list中
        List<Integer> integers = Arrays.asList(1, 3, 2);
        list.addAll(2,integers);
        System.out.println(list);
        System.out.println( list.get(3));

    }
}


/**二,集合框架
 * --- collection接口:单列集合,用来存储一个个的对象
 *      ---Set接口:存储无序的,不可重复的数据 ---》数学中的集合
 *          ----HashSet:存储无序的,不可重复的数据;线程不安全的;可以存储null值
 *              ----LinkedHashSet:是HashSet的子类;遍历数据时,可以按照添加的顺序去遍历
 *          ----TreeSet:可以按照添加的对象的指定的属性,进行排序
 *
 *
 *   1,set接口中,没有额外定义方放,都是用Collection声明过的方法
 *      要求:向Set中添加的数据,其所在类一定要重写hashCode()和equals()方法
 *      要求:重写的hashCode()和equals()方法,尽可能要保证一致性:相等的对象必须要有相同的hash值
 *      以HashSet为例
 *      无序性:不是随机性,在底层不是根据索引顺序来存储的,而是根据数据的hash值来存储的
 *      不可重复性:保证添加的元素
 *
 *
 *   2,以hashset为例
 *   我们向HashSet中添加元素,首先调用元素a所在类的hashcode()方法,计算a的hash值,
 *   此hash值,接着通过某种算法计算出在HashSet底层数组中存放的位置,(索引位置),
 *   判断索引位置上是否有相同的数据:
 *      如果没有其他元素,直接添加---->情况1
 *      如果有其他的元素,比较他们的hash值:
 *          如果不同:就添加成功---->情况2
 *          如果相同:就用新添加的元素的所在类的equals()方法与索引位置元素比较
 *              返回的是false就添加成功---->情况3
 *              是ture就添加失败
 *   对于情况2与情况3而言,与已经存在索引位置上的元素以链表的方式存储
 *   jdk1.7时:新元素放到数组中,指向之前元素
 *   jdk1.8时:老元素在数组中指向新元素
 *   hashSet 底层是数组+链表的结构
 * @author rieson
 * @create 2021-01-11-9:33
 */
public class SetTest {
    @Test
    public void test1(){
        Set<Object> set = new HashSet<>();
        set.add(123);
        set.add(456);
        set.add("qwe");
        set.add("asd");
        set.add(null);
        set.add(new Date());
        set.add(new String("unb"));
        System.out.println(set);
        Iterator<Object> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
    @Test
    public void test2(){
        //LinkedHashSet 作为HashSet的子类,再添加数据时,每个数据还维护了,两个引用,
        // 记录此数据前后数据和,
        //优点:对于比较频繁的遍历操作,LinkedHashSet效率高于HashSet.
        Set<Object> set = new LinkedHashSet<>();
        set.add(123);
        set.add(456);
        set.add("qwe");
        set.add("asd");
        set.add(null);
        set.add(new Date());
        set.add(new String("unb"));
        System.out.println(set);
        Iterator<Object> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
    @Test
    public void test3(){
        //向TreeSet中添加数据,要求是相同类的对象
        //两种排序方式:自然排序:Comparable,定制排序:Comparator
        //自然排序中,比较两个对象是否相同的标准:compareTo()返回0,不是equals()
        //定制排序略
        Set<Object> set = new TreeSet<>();
        set.add(123);
        set.add(456);

        System.out.println(set);
        Iterator<Object> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
}

/**
 * 1, Map接口:双列集合,用来存储一对(key---value)一对的数据
 *     ------HashMap:作为Map的主要实现类;线程不安全,效率高;可以存储null的key value值
 *          ----- LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历
 *                          原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个
 *                          元素,对于频繁的遍历操作,此类要效率要高与HashMap
 *     -----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序,或定制排序
 *                  底层使用的是红黑树
 *      ----Hashtable:作为Map的古老实现类;线程安全,效率低;不能存储null的key value值
 *          ----- Properties:常用来处理配置文件。key和value都是String类型的。
 *
 *      HashMap的底层:数组+链表(1.7)
 *                    数组+链表+红黑树(1.8)
 *
 *      面试题:
 *      1,HashMap的底层实现原理
 *      2,HashMap与Hashtable的异同
 *      3,
 * 2,Map结构的理解:
 *      Map 中的key:无序的,不可重复的,使用Set存储所有的Key ---》Key所在的类需要重写equals()方法和hashcode()方法
 *      value:无序的,可重复的,使用Collection存储所有的value---》value所在类需要重写equals()方法
 *      一个键值对:key-value构成一个Entry对象
 *      Map中的Entry:无序的,不可重复的,使用Set来存储所有的Entry
 *
 * 3,HashMap的底层实现原理:
 *       (jdk7)
 *      HashMap map = new HashMap();
 *      在实例化以后,底层创建了长度是16的一维数组Entry[] table.
 *      ....已经执行过很多次put...
 *      map.put(key1,value1):
 *      首先调用的key1所在类的hashCode()计算key1的哈希值此哈希值经过某种算法计算以后,得到Entry数组中的存放位置
 *      如果此位置上为空,此时的key1-value1添加成功,-----情况1
 *      如果此位置上有一个,或多个元素(以链表的方式存储),比较key1和已经存在的一个或多个元素的key的哈希值
 *              如果key1的哈希值与所有的元素的哈希值都不同时,则key1添加成功-----情况2
 *              如果key1的哈希值与其中任何一个元素的哈希值一样时,继续比较,调用key1所在类的equals()方法
 *              如果返回的是false,则key1添加成功。----情况3
 *              如果返回的是true,此时已经存储的key,保持不变,value值被key1的value替换
 *         补充:关于情况2,情况3:此时的key1-value1和原来的数据以链表的方式存储
 *
 *         再不断的添加过程中,会涉及到扩容问题,当超出临界值时,并且下一个添加的索引位置上不为空
 *         默认的扩容方式:扩容为原来容量的2倍,将原有的数据复制过来
 *
 *        (jdk8)相较于jdk7底层实现方面的不同:
 *
 *  *      1,new HashMap();在实例化以后,底层没有创建了长度是16的一维数组Entry[] table.
 *         2,jdk8底层的数组是:Node[],而非Entry[]
 *         3,首次使用put()方法时,底层创建建了长度是16的数组
 *         4,jdk7底层只有:数组+链表。jdk8中的底层结构:数组+链表+红黑树。
 *              当数组的某一个索引位置上的元素以链表的方式存在的个数大于8 且当前数组的长度大于64时
 *              此时索引位置上的所有数据改为使用红黑树存储
 *
 *
 *
 *
 *
 *
 *
 *
 * @author rieson
 * @create 2021-01-11-17:57
 */
public class MapTest {
    @Test
    public void test3(){
        Map map = new HashMap<>();
        map.put("aa",123);
        map.put(123,456);
        map.put("AA","bb");
        //遍历所有的key集:KeySet
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //遍历所有的value:values()
        Collection values = map.values();
        for (Object o : values ){
            System.out.println(o);
        }
        //遍历所有的key-value
        Set set1 = map.entrySet();
        Object a=new Object();
        System.out.println("------------------");


        for (Object o:set1){
            System.out.println(o);
        }
        System.out.println("****************");
        //方式一
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()){
            Object next = iterator1.next();
            Map.Entry m = (Map.Entry) next;
            System.out.println(m.getKey()+"------->"+m.getValue());
            System.out.println("+++++++++++++++++++++++");
            //System.out.println(iterator1.next());
        }
        //方式二
        Set set2 = map.keySet();
        Iterator iterator2 = set2.iterator();
        while (iterator2.hasNext()){
            Object key = iterator2.next();
            Object o = map.get(key);
            System.out.println(key+"======="+o);
        }

    }
    @Test
    public void test2(){

        Map map = new HashMap<>();
        //put(key,value):添加数据
        map.put("aa",123);
        map.put(123,456);
        map.put("AA","bb");
        System.out.println(map);
        //putAll(Map m):将m集合的数据添加到map中
        HashMap m  = new HashMap<>();
        m.put(000,111);
        map.putAll(m);
        System.out.println(map);

        //remove(123):删除指定key值的key-value
        Object remove = map.remove(123);
        System.out.println(remove);
        System.out.println(map);
        //map.clear():清空集合中的元素
        map.clear();
        //map.get(111):获取指定key的value值
        map.get(000);
        // map.isEmpty():Map是否为空
        map.isEmpty();
        //map.containsKey(000);是否包含key值
        map.containsKey(000);
        //map.containsKey(000);是否包含制定的value
        map.containsValue(111);

    }
    @Test
    public void test1(){
        Map map = new HashMap<>();
        map.put(null,null);

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值