Java--集合

集合

面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,要对对象进行存储,另一方面,使用Array具有一些弊端,而java集合就像一种容器,可以动态的把多个对象的引用,放入容器中。

分类

​ java集合可以分为Collection体系和Map体系(接口)

​ Collection接口:单列数据,定义了一组对象的方法的集合

​ List:元素有序,可重复的集合

​ Set:元素无序、不可重复的集合

​ Map接口:双列数据,保存具有映射关系的 “key-value对” 的集合

Collection接口

单列集合,用来存储一个一个的对象

Collection常用方法

package javaSE.Set;

import javax.annotation.Generated;
import java.util.*;

/**
 * 1, 集合和数组都是用于存储多个数据
 *
 * 2, 数组在村塾多个数据方面的特点
 *      >数组初始化之后长度确定
 *      >定义数组后必须声明类型,其元素类型也确定了
 *     缺点
 *      >初始化之后长度不可修改
 *      >数组中提供的方法有限,对于添加删除,插入,非常不便
 *      >获取数组中实际元素个数,数组数组中没有属性和方法可用
 *      >数组存储特点:有序。可重复。对于无序,不可重复不能满足
 *
 *
 * 二、集合框架
 *
 *
 * 三、Collection接口中方法的使用
 *
 * 说明;
 *  1,向Collection接口的实现类的对象中添加数据obj的时候要求obj所在类要重写equal方法
 *
 * @Author: Thewind
 * @Date: 2021/1/26 16:17
 */
public class CollectionTest {
    public static void main(String[] args) {
        Test test = new Test();
        //test.test1();
//        test.test2();
//        test.test3();
        test.test4();
    }

}
class Test{
    public void test1(){
        Collection coll = new ArrayList();

        //1,add(Object e);将元素添加到集合coll中
        coll.add("AA");
        coll.add("BB");
        coll.add(123);
        coll.add(new Date());

        //2,size();获取添加的元素个数--->4
        System.out.println(coll.size());

        //3,addAll(Collection coll1);将coll1中的元素全部添加到coll中
        Collection coll1 = new ArrayList();
        coll1.add("CC");
        coll1.add("DD");
        coll.addAll(coll1);

        System.out.println(coll.size());
        System.out.println(coll);

        //4,clear();清空集合元素,对象仍然存在
        coll1.clear();

        //5,isEmpty();判断当前集合是否为空
        System.out.println(coll1.isEmpty());


        coll.add(new Person("张三",20));
        //6,contains(Object obj);判断当前集合中是否包含obj,
        System.out.println(coll.contains("CC"));
        System.out.println(coll.contains(new String("AA")));
        //返回值是True,判断的是内容,不是地址,因为contain使用的是equal(),而String重写了equal,只比较内容
        //所以下面语句调用结果为false,此处contains调用的是Person类
        //的equal()但Person中没有重写equal()方法,所以还是判断地址
        System.out.println( "重写后。。。。" + coll.contains(new Person("张三", 20)));
        //contains(Object ob)会调用ob所在类的equal方法

        //7,containsAll(Collection coll);判断coll中的所有元素是否都存在于当前集合中
        System.out.println("containsAll**********************");
        Collection coll2 = Arrays.asList("AA","BB","CC");
        System.out.println(coll.containsAll(coll2));

    }

    public void test2(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("张三",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //8,remove(Object obj),移除的值存在就移除该值并返回true,否则返回false
        System.out.println(coll.remove(123));
        System.out.println(coll);

        //9,removeAll(Collection coll),当前集合中删除coll中所有元素,但移除的是共有部分
        Collection coll1 = Arrays.asList(456,true);
        coll.removeAll(coll1);
        System.out.println(coll);

        //10,retainAll(Collection coll);求两集合交集,并返回给当前集合
        System.out.println("********************");
        Collection coll2 = Arrays.asList(789,false);
        //coll.retainAll(coll2);
        System.out.println(coll);



    }
    public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("张三",20));
        coll.add(new String("Tom"));
        coll.add(false);


        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add(456);
        coll1.add(new Person("张三",20));
        coll1.add(new String("Tom"));
        coll1.add(false);

        //11,equals(Object obj);判断当前集合和形参集合的元素是否相同,至于是否有序需要看具体的实现类
        System.out.println(coll.equals(coll1));
    }
    public void test4(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("张三",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //12,hashCode();返回当前对象的哈希值
        System.out.println(coll.hashCode());

        //13, toArray();集合转换为数组
        Object[] array = coll.toArray();
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        //拓展----》数组也可以转换为集合,调用Arrays类的静态方法asList()
        List<String> arr = Arrays.asList(new String[]{"AA", "BB", "CC"});
        System.out.println(arr);

        List<int[]> arr1 = Arrays.asList(new int[]{123, 456});
        System.out.println(arr1);//1,这种情况List将整个new当做一个变量存储因为是类型的白变量

        List<Integer> arr2 = Arrays.asList(new Integer[]{123, 456, 789});
        System.out.println(arr2);//2,这种情况包装类,集合会分别存储



    }

}

迭代器

在这里插入图片描述

package javaSE.Set;

import sun.misc.PostVMInitHook;

import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 *
 * 集合 元素的遍历,使用Iterator接口
 * Iterator内部方法,hasNext(),和 Next()
 * 注意:结合对象每次调用iterator()方法都得到一个全新的迭
 * 代对象,默认游标都在集合的第一个元素
 *
 * @Author: Thewind
 * @Date: 2021/1/27 0:06
 */
public class IteratorTest {
    public static void main(String[] args) {
        Testt t = new Testt();
        t.test1();
    }
}
class Testt{
    public void test1(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("张三",20));
        coll.add(new String("Tom"));
        coll.add(false);


        //iterator();返回Iterator接口的实例,用于遍历集合元素,放在IteratorTest.java中测试
        Iterator iterator = coll.iterator();
        //注意,Iterator不是容器




        while(iterator.hasNext()){
            //next()1,指针下移 2,返回下移后位置的元素
            System.out.println(iterator.next());

        }

        Iterator iterator1 = coll.iterator();
        //测试Iterator中的remove方法
        //如果还未调用next()方法或者在上一次调用next方法之后已经调用了remove方法
        //再调用remove方法会报错
        while (iterator1.hasNext()){
            Object object = iterator1.next();
            if ("Tom".equals(object)){
                iterator1.remove();
            }
        }

    }
}

//扩展  foreach遍历集合数组

package javaSE.Set;

import com.sun.org.apache.bcel.internal.generic.NEW;

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

/**
 *
 * JDK 5.0新增了foreach循环,用于遍历和和数组
 * 
 * @Author: Thewind
 * @Date: 2021/1/27 16:47
 */
public class ForTest {
    public static void main(String[] args) {
        Test2 t = new Test2();
        t.test1();

    }

}

class Test2{
    public void test1(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("张三",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //for(集合元素的类型 局部变量 : 局部变量)
        //将集合中的元素赋值给局部变量
        //内部仍然调用的迭代器
        for (Object object : coll){
            System.out.println(object);
        }
        int[] arr = new int[]{1,2,3,4,5,6};
        for (int i : arr) {
            System.out.println(i);
        }
    }

}

List接口

元素有序,可重复的集合. 。常用于存储动态数组

总结源码分析
List存储有序、可重复的对象
* ArrayList----作为List的主要实现类 JDK1.2  线程不安全,效率高,底层使用Object[]存储
* LinkedList---底层使用双向链表存储,适用于频繁的插入删除操做  JDK1.2
* vector------作为List古老的实现类 JDK1.0  线程安全,效率低底层也是Object[] 数组存储
*
* 面试题,比较ArrayList和LinkdList和vector三者的异同
*同、三者都实现了List接口,存储的数据特点相同存储有序可重复的数据
* 不同、上面
*ArrayList源码分析
*  JDK 7 情况下
*      ArrayList list = new ArrayList();//底层创建了一个长度为10的Object类型的数组
*      list.add(123);//elementData[0] = new Integer(123);
*      ...
*      list.add(11);//如果此次添加导致底层的elementData的容量不够,则扩容
*      默认扩容为原来的1.5倍,同时将原有数组的数据复制到新数组中
*
*      建议:建议开发中使用带参的构造器
*
*   JDK 8情况下
*       ArrayList list = new ArrayList();//底层Object[] elementData 初始
*       化为{},并没有创建长度为10的数组
*
*       list.add(123);//第一次调用add()时底层才创建长度为10的数组并将数据添加到elementData中
*       。。。
*       后续添加与扩容和JDK 7相同
*    小结:JDK 7中的创建类似于单列的饿汉式,儿JDK 8 中的创建类似于单利的懒汉式,延迟了数组的创建,可节省内存
*
*LinkList的源码分析
*      LinkedList list = new LinkList();内部声明Node类型的first和last属性,默认值为NULL
*      list.add(123)://将123封装到Node中,创建Node对象
*      其中Node定义为:双向链表
*       private static class Node<E> {
*         E item;
*         Node<E> next;
*         Node<E> prev;
*
*         Node(Node<E> prev, E element, Node<E> next) {
*             this.item = element;
*             this.next = next;
*             this.prev = prev;
*         }
*     }
*
*vector源码分析
* JDK 7 和JDK 8 vector()构造器创建对象时,底层都创建了长度为10的数组
* 在扩容方面,默认扩容为原来数组的 2倍 
list接口的常用方法

在这里插入图片描述

ArrayList
LinkList
Vector

Set接口

元素无序、不可重复的集合。

/无序性

  • 无序性并不是随机性

    以HashSet为例,存储的数据按照Hash值在数组中存储
    *

  • /不可重复性:

  • 保证添加元素按照equal()判断时,不能true

set没有提供额外的方法

set判断两个对象是否相同不是使用的 ==运算符,而是使用equal()方法

向Set中添加数据,其添加的数据所在的类一定要重写hashCode()和equal()方法,重写后要求相等的对象必须具有相等的散列值

向Set中添加元素的过程

以HashSet为例:
*我们想HashSet中添加元素a ,首先调用元素a所在类的hashcode()方法,计算a的hash值

  • 此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(索引值)判断数组此位置上是否已经有元素
  • 若没有,直接添加成功, -----情况一
  • 若有元素b(或者以链表的形式存在多个元素)则比较元素a和b的hash值
    •  如果hash值不相同则添加成功   ------情况二
      
    •  如果hash值相同,进而需要调用元素a所在类的equal()方法,
       *          equal()方法返回true,添加失败,
       *          equal()方法返回false,添加成功   ------情况三
      
  • 对于添加成功的情况二和情况三而言新添加的元素和原先已经存在的数据以链表的形式存储
  • JDK 7 : 元素a放在数组中,指向原来的元素
  • JDK 8 : 原来的元素放在数组中,指向元素a
HashSet

由源码可知HashSer底层是HashMap

做为Set接口的主要实现类,线程不安全可以存储null值

HashSet底层是数组+链表

HashSet底层数组长度为16,当数组的使用率超过0.75时,数组就会扩展为原来的2倍,依次为32、64、128…

LinkHashSet

是HashSet的子类,遍历其内部数据时可以按照添加的顺序去遍历

其在底层数组中的存储仍然是按hash值无序存储的,只是LinkedHashSet中还维护了两个地址,构成一个双向链表来记录添加顺序,故可以按序遍历

优点:对于频繁的遍历操作,LinkedHashCode效率高于HashSet

TreeSet

要求放入TreeSet的元素是同一类型,可以按照添加对象的指定属性进行排序,按照二叉排序树排列

两种排序方式:自然排序和定制排序

​ 自然排序:比较两个 对象是否相等的标准是:compareTo(Object obj)方法是不是返回0,不再是equals()方法

package javaSE.SetJavaSet;

import java.util.Objects;

/**
*实现compareTo方法
 * @Author: Thewind
 * @Date: 2021/1/28 16:11
 */
public class Users implements Comparable{
    private String name;
    private int aga;

    public Users(String name, int aga) {
        this.name = name;
        this.aga = aga;
    }

    public Users() {
    }

    public String getName() {
        return name;
    }

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

    public int getAga() {
        return aga;
    }

    public void setAga(int aga) {
        this.aga = aga;
    }

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

    @Override
    public boolean equals(Object o) {
        //System.out.println("equals....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Users users = (Users) o;
        return aga == users.aga &&
                Objects.equals(name, users.name);
    }

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


    //按照姓名,从小到大排列
    @Override
    public int compareTo(Object o) {
        if (o instanceof  Users){
            Users users = (Users)o;
//            return this.name.compareTo(users.name);
            int compare = -this.name.compareTo(users.name);
            if (compare != 0){
                return compare;
            }else{
                return Integer.compare(this.aga , users.aga);
            }
        }else{
            throw new RuntimeException("输入的类型不匹配");
        }

    }
}

​ 定制排序:(comparator接口)比较两个 对象是否相等的标准是:compare(Object o1, Object o2)方法是不是返回0,不再是equals()方法

package javaSE.SetJavaSet;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
 *
 *
 * @Author: Thewind
 * @Date: 2021/1/28 17:02
 */
public class TreeSetTest {
    public static void main(String[] args) {
        Test1 test = new Test1();
        //test.test1();
        test.test2();
    }
}
class Test1{

    //自然排序
    public void test1(){
        TreeSet treeSet = new TreeSet();
        //报错,TreeSet中添加的数据必须是相同类的对象
//        treeSet.add(123);
//        treeSet.add(456);
//        treeSet.add("AA");
//        treeSet.add(new Users("Tom" , 20));

        //举例一 结果-32,8,12,23,25
//        treeSet.add(12);
//        treeSet.add(23);
//        treeSet.add(-32);
//        treeSet.add(25);
//        treeSet.add(8);

        //举例二 抛异常ClassCastException,因为并未定义比较方法
        treeSet.add(new Users("Tom" , 20));
        treeSet.add(new Users("Jerry" , 32));
        treeSet.add(new Users("Mike" , 65));
        treeSet.add(new Users("Jack" , 33));
        treeSet.add(new Users("Jack" , 53));
        //名字从大到小,年龄从小到大

        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }

    //定制排序,使用Comparator接口
    public void test2(){
         
        TreeSet treeSet = new TreeSet(com);
        treeSet.add(new Users("Tom" , 20));
        treeSet.add(new Users("Jerry" , 32));
        treeSet.add(new Users("Mike" , 65));
        treeSet.add(new Users("Jack" , 33));
        treeSet.add(new Users("Jack" , 53));

        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
}

Map接口

双列集合,保存具有映射关系的 “key-value对” 的集合

Map接口的继承树

在这里插入图片描述

key-value理解

key和value的关系像是函数的自变量和函数值的关系,不同的自变量可以有相同的函数值,但自变量不能相同。即key值不能重复,但value值可以相同。

key:无序,不可重复,使用set存储 —>key所在的类要重写equals和hashCode函数

value:无序,可重复,使用collection存储—>value所在的类要重写equals

Entry:无序,不可重复,用set存储

实际上Map中存放的是一个Entry对象,Entry具有两个属性,key和value。

Map常用方法

添加、删除、修改操作

​ Object put(Object key,Object value);将指定key-value添加到(或修改到)当前map对象中

​ void putAll(Map m);将m中所有的key-value存储到当前map中

​ Object remove(Object key);移除指定key的key-value对,并返回value

​ void clear();清空当前map中的所有数据

元素查询的操作

​ Object get(Object key);获取指定key对应的value

​ boolean containsKey(Object key);是否包含指定的key

​ boolean containsValue(Object value);是否包含指定的value

​ int size();返回map中key-value对的个数

​ boolean isEmpty();判断当前map是否为空

​ booolean equals(Object obj);判断当前map和参数对象obj是否相等

元视图操作方法

​ Set keySet();返回所有的key组成的set集合

​ Collection values();返回所有value构成的Collecton集合

​ Set entrySet();返回所有key-value对构成的set集合

package javaSE.JavaMap;

import java.util.*;

/**
 *
 * 添加、删除、修改操作
 *
 * ​	Object put(Object key,Object value);将指定key-value添加到(或修改到)当前map对象中
 *
 * ​	void putAll(Map m);将m中所有的key-value存储到当前map中
 *
 * ​	Object remove(Object key);移除指定key的key-value对,并返回value
 *
 * ​	void clear();清空当前map中的所有数据
 *
 * 元素查询的操作
 *
 * ​	Object get(Object key);获取指定key对应的value
 *
 * ​	boolean containsKey(Object key);是否包含指定的key
 *
 * ​	boolean containsValue(Object value);是否包含指定的value
 *
 * ​	int size();返回map中key-value对的个数
 *
 * ​	boolean isEmpty();判断当前map是否为空
 *
 * ​	booolean equals(Object obj);判断当前map和参数对象obj是否相等
 *
 * 元视图操作方法
 *
 * ​	Set keySet();返回所有的key组成的set集合
 *
 * ​	Collection values();返回所有value构成的Collecton集合
 *
 * ​	Set entrySet();返回所有key-value对构成的set集合
 * @Author: Thewind
 * @Date: 2021/1/29 1:43
 */
public class MapTest {
    public static void main(String[] args) {
        Test test = new Test();
//        test.test1();
//        test.test2();
        test.test3();
    }
}

class Test{
    public void test1(){
        //1.put();
        Map map =new HashMap();
        map.put(123,"AA");
        map.put(456,"BB");
        map.put(12,"CC");
        //void putAll(Map m);将m中所有的key-value存储到当前map中
        map.put(123,"DD");
        System.out.println("HashMap输出:" + map);
        System.out.println("******************");
        Map m =new HashMap();
        m.put(45,"HH");
        m.put(56,"GG");
        m.put(84,"HH");
        map.putAll(m);
        //void putAll(Map m);将m中所有的key-value存储到当前map中
        System.out.println("HashMap输出:" + map);

        //Object remove(Object key);移除指定key的key-value对,并返回value
        System.out.println("***************************");
        System.out.println(map.remove(45));
        System.out.println("HashMap输出:" + map);

        //void clear();清空当前map中的所有数据
        //int size();返回map中key-value对的个数
        System.out.println("*****************");

        //void clear();清空当前map中的所有数据
        map.clear();//clear只是清空了数据,并不是map = null

        //boolean isEmpty();判断当前map是否为空
        System.out.println(map.isEmpty());

        System.out.println(map.size());



    }
    void test2(){
        Map map =new HashMap();
        map.put(123,"AA");
        map.put(456,"BB");
        map.put(12,"CC");
       // Object get(Object key);获取指定key对应的value
        System.out.println("get()输出" + map.get(123));
        System.out.println("************");

        //   boolean containsKey(Object key);是否包含指定的key
        // ​ boolean containsValue(Object value);是否包含指定的value
        System.out.println("containsKey()输出" + map.containsKey(123));
        System.out.println("containsValue()输出" + map.containsValue("CC"));
    }




    /**
     *  * 元视图操作方法
     *  *
     *  * ​	Set keySet();返回所有的key组成的set集合
     *  *
     *  * ​	Collection values();返回所有value构成的Collecton集合
     *  *
     *  * ​	Set entrySet();返回所有key-value对构成的set集合
     */

    public void test3(){

        Map map =new HashMap();
        map.put(123,"AA");
        map.put(456,"BB");
        map.put(12,"CC");

        //遍历所有的key集,keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }

        //遍历所有的value值,Collection values();返回所有value构成的Collecton集合
        Collection values = map.values();
        Iterator iterator1 = values.iterator();
        //迭代器遍历
        while (iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
        //foreach遍历
        for (Object obj : values){
            System.out.println(obj);
        }

        //遍历key-value对,
        // 方式一:Set entrySet();返回所有key-value对构成的set集合
        Set set1 = map.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }

        //方式二,通过key值获取value
        while (iterator.hasNext()){
            //System.out.println(iterator.next());
            Object key = iterator.next();
            Object value = map.get(key);
            System.out.println(key + "==" + value);
        }

    }


}



HashMap

作为Map的主要实现类,线程不安全,效率高,能存储null的key和value

HashMap底层 数组+链表 (JDK 7即之前)

​ 数组+链表 +红黑树(JDK 8)

HashMap底层实现原理 (以JDK 7为例)

HashMap map = newHashMap();

在实例化以后,底层创建了长度为16 的一维数组Entry[] table,

…执行多次put()后…

map.put(hey1,value1);

首先,调用key1所在类的hashCode()函数计算key1的哈希值,此哈希值经过某种算法计算以后得到Entry数组中的存放位置。

如果此位置上数据为空,就添加成功-----情况一

如果此位置上的数据不为空(此位置上存在一个或者多个数据(以链表存储)),比较当前的key1和已经存在的一个或者多个数据的哈希值是否相同

​ 如果key1的哈希值和已经存在的数据的哈希值都不同,此时key1-value1添加成功----情况二

​ 如果key1的哈希值和已经存在的某个数据(key2-value2)的哈希值相同,继续比较调用key1所在类equals(key2)方法,比较:

​ 如果equals返回false,key1-value1添加成功----情况三

​ 如果equals返回true,使用value1替换想听key的value值(所以put还可以修改)

关于情况二和情况三,此时key1-value1和原来的数据以链表的方法是存储

在不断的添加过程中,当超出临界值(且要存放的位置非空)默认扩容方式是扩容为原来的2倍,并将数据复制过来

(此处HashMap并不是等数组全部存储满之后才扩容,是因为HashMap根据哈希值存储数据这可能会导致数组的某一处数据堆积但数组仍然没有存满,所以可以

通过扩容来降低数据堆积的概率)

JDK8相较于JDK7 在底层方面的不同

1.new HashMap()底层没有创建一个长度为16的数组

2,JDK8 底层数组是 Node[],而不是Entry数组

3,JDK8 中首次调用put方法时底层创建长度为16的数组

4,JDK7底层结构中只有:数组+链表而JDK8底层结构中有:数组+链表+红黑树

​ 当数组的某一个索引位置上的数据以链表形式存储的数据个数 > 8且当前数组长度 > 64时,此时此索引位置上的数据改用红黑树存储(目的:方便查找,二叉排序树查找效率高)

HashMap源码中的重要常量

DEFAULT_INITIAL_CAPACITY: HashMap的默认容量 16

MAXIMUN_CAPACITY: HashMap的自大支持容量 2^30;

DEFAULT_LOAD_FACTOR: HashMap的默认加载因子

TREEIFY_THRESHOLD:Bucket中链表链表长度大于该默认值,转化为红黑树

MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量(当桶中的Node容量大到需要变红黑是时,若hash表容量小于MIN_TREEIFY_CAPACITY时此时应执resize扩容操作这个MIN_TERRIFY_CAPACITY的值至少是TERRIFY_THRESHOLD的4倍。)

table: 存储元素的数组,总是2的n次幂

entrySet:存储具体元素的值

size: HashMap中存储的键值对的数量

modCount:HashMap扩容和结构改变的次数

thresdold: 扩容的临界值,=容量 * 填充因子

loadFactor: 填充因子

LinkHashMap

是HashMap的子类,可以按照存储顺序实现遍历

有序的键值对在原有的HashMap底层基础上,添加了一对指针,指向前一个和后一个数据指针,对于频繁的操作,此执行效率浩宇HashMap

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

        Map map1 = new LinkedHashMap();
        map1.put(123,"AA");
        map1.put(456,"BB");
        map1.put(12,"CC");
        System.out.println("LinkedHashMap输出:" + map1);//按照输入顺序输出

LinkedHashMap重写了上述方法,用before和after记录数据存储的先后顺序

TreeMap

保证按照添加的key-value对进行排序,实现排序遍历,(此时考虑key的自然排序和定制排序)

底层使用红黑树

package javaSE.JavaMap;

import com.sun.org.apache.bcel.internal.generic.NEW;
import javaSE.SetJavaSet.Users;

import java.util.*;

/**
 *向TreeMap中添加key-value时要求key必须是统一个类创建的对象
 * 因为要按照key进行排序:自然排序和定制排序
 *
 * @Author: Thewind
 * @Date: 2021/1/30 16:29
 */
public class TreeMapTest {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
       //test1.test1();
        test1.test2();

    }

}

class Test1{

    //自然排序
    public void test1(){
        TreeMap treeMap = new TreeMap();
        Users u1 = new Users("Tom" , 21);
        Users u2 = new Users("Jerry" , 21);
        Users u3 = new Users("Jack" , 24);
        Users u4 = new Users("Marry" , 18);
        treeMap.put(u1 , 98);
        treeMap.put(u2 , 84);
        treeMap.put(u3 , 91);
        treeMap.put(u4 , 100);

        Set set1 = treeMap.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()) {
            //System.out.println(iterator2.next());
            Object next = iterator2.next();
            Map.Entry entry = (Map.Entry)next;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
        }

    }

    //定制排序
    public void test2(){
        Comparator com = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Users && o2 instanceof Users ){
                    Users u1 = (Users)o1;
                    Users u2 = (Users)o2;
                    return Integer.compare(u1.getAga(),u2.getAga());
                }
                throw new RuntimeException("输入的数据类型不匹配");

            }
        };
        TreeMap treeMap = new TreeMap(com);
        Users u1 = new Users("Tom" , 21);
        Users u2 = new Users("Jerry" , 12);
        Users u3 = new Users("Jack" , 24);
        Users u4 = new Users("Rose" , 18);
        treeMap.put(u1 , 98);
        treeMap.put(u2 , 84);
        treeMap.put(u3 , 91);
        treeMap.put(u4 , 100);

        Set set1 = treeMap.entrySet();
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()) {
//            System.out.println(iterator1.next());
            Object next = iterator1.next();
            Map.Entry entry = (Map.Entry) next;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
        }
    }


}

Hashtable

古老的实现类,线程安全,效率低,不能存储null的key和value

Properties

常用于处理配置文件,key和value都是string类型

存取数据时建议使用setProperty(String key,String value)

方法和getProperty(String key)方法

Properties pos = new Properties();
pros.load(new FileInputStream("jdbc.properties"));
String user = pos.getProperty("user");
System.out.println(user);
package javaSE.JavaMap;

import java.io.FileInputStream;
import java.util.Properties;

/**
 *
 * 存取数据时建议使用setProperty(String key,String value)
 *
 * 方法和getProperty(String key)方法
 * @Author: Thewind
 * @Date: 2021/1/30 20:17
 */
public class PropertiesTest {
    public static void main(String[] args) throws Exception {
        Properties pros = new Properties();
        FileInputStream fis = new FileInputStream("F:\\Developer\\javaCode\\JavaSE\\基础语法\\res\\jdbc.properties");
        pros.load(fis);
        String name = pros.getProperty("name");
        String password = pros.getProperty("password");
        System.out.println("name=" + name + "  password=" + password);
    }
}

Collections工具类

collections是一个操作Set、List和Map等集合的工具类

Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了 对集合对象设置不可变,对集合对象实现同步控制的方法。

排序操作(均为static方法)

​ reverse(List);反转List中的元素

​ shuffle(List);对List集合中的元素进行随机排序

​ sort(List);按照元素的自然顺序对List集合中的元素按升序进行排序

​ sort(List, Comparator);根据指定的Comparator产生的顺序对List集合元素进行排序

​ swap(List, int, int);将指定List集合中的i处元素和j处元素进行交换

​ Object max(Collection);根据元素的自然排序,返回给定集合的最大元素

​ Object max(Collection, Comparator);按照定制排序返回集合中的最大元素

​ Object min(Collection);

​ Object min(Collection, Comparator);

​ int frequency(Collection, Object);返回指定集合中指定元素的出现次数

​ void copy(List dest, List src);将src内容复制到dest中

​ boolean replaceAll(List list, Object olcVal, Object newVal);使用新值替换List对象总的所有旧值。

package javaSE.JavaMap;

import javaSE.SetJavaSet.Users;

import java.util.*;

/**
 * Collections 操作Collection和Map的工具类
 * @Author: Thewind
 * @Date: 2021/1/30 20:55
 */
public class CollectionsTest {
    public static void main(String[] args) {
        Test2 test2 = new Test2();
        test2.test1();
    }
}

class Test2{
    public void test1(){
        List list = new ArrayList();
        list.add(120);
        list.add(94);
        list.add(51);
        list.add(85);
        list.add(43);
        list.add(214);
        System.out.println("原List  " + list);
        //reverse(List);反转List中的元素
        Collections.reverse(list);
        System.out.println("reverse之后的List" + list);
        //shuffle(List);对List集合中的元素进行随机排序
        Collections.shuffle(list);
        System.out.println("shulffle之后的List" + list);
        //sort(List);按照元素的自然顺序对List集合中的元素按升序进行排序
        Collections.sort(list);
        System.out.println("sort之后的List" + list);
        //sort(List, Comparator);根据指定的Comparator产生的顺序对List集合元素进行排序


        //swap(List, int, int);将指定List集合中的i处元素和j处元素进行交换
        Collections.swap(list,1,2);
        System.out.println("swap之后的List" + list);

        //void copy(List dest, List src);将src内容复制到dest中

        //错误
//        List dest = new ArrayList();
//        Collections.copy(dest,list);
        //报错,IndexOutOfBoundsException: Source does not fit in dest
        //原因,copy源码中有如下代码
//        int srcSize = src.size();
//        if (srcSize > dest.size())
//            throw new IndexOutOfBoundsException("Source does not fit in dest");
        //故报错

        //正确
        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest,list);
        System.out.println("copy之后的dest" + dest);
        //此种方法新建集合中的数据全为NULL

    }
}

Collection 常用方法:同步控制

由于Arraylist和HashMap都是线程不安全的,,故Collection类提供了多个synchronized()方法,该方法可将指定集合包装成同步的集合,从而可以解决多线程并发访问集合时的线程安全问题

在这里插入图片描述

public void test2(){
        List list = new ArrayList();
        list.add(120);
        list.add(94);
        list.add(51);
        list.add(85);
        list.add(43);
        list.add(214);

        //返回的list1即为线程安全的List
        List list1 = Collections.synchronizedList(list);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值