Java集合框架


Java集合可分为Collection和Map两种体系

  • Collection接口:单列数据,应以了存取一组对象的方法的集合
    • List:元素有序,可重复的集合
      • ArrayList:作为List接口的只要实现类,线程不安全,效率高,底层使用Object[] elementData存储
      • LinkedList:对于频繁的插入,删除操作,使用此类效率高,底层使用双向链表存储
      • Vector:作为List接口的古老实现类,线程安全,效率低,底层使用Object[] elementData存储
    • Set:元素无序,不可重复的集合,如果将两个相同的元素加入集合中,add方法将返回false。
      • HashSet:
        ①不能保证元素的排列顺序
        ②顺序有可能发生变化,
        ③ 不是同步的
        ④集合元素可以是null,但只能放入一个null
        当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
        HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等
        注意! 如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其 hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

        • LinkedHashSet:作为HashSet的子类,LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
      • TreeSet:可以按照添加对象的指定属性,进行排序(自然排序or定制排序),不允许放入null。TreeSet判断两个对象是否相等的方式是两个对象通过equals方法返回true,或者通过CompareTo方法比较返回0

  • Map接口:双列数据,保存具有映射关系“key-value对”的集合—类似于函数映射 y = f(x)。
    • HashMap:Map的主要实现类;线程不同步;可以存储null的key和value,允许一条记录的键为null,允许多条记录的值为null;
      • LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历;在原有的HashMap底层结构基础上添加了一对指针,指向前一个和后一个结点;对于频繁的遍历操作,此类执行效率高于HashMap。
    • TreeMap:保证按照添加的key-value进行排序,实现排序遍历,此时考虑自然排序或者定制排序。底层使用红黑树实现。
    • Hashtable:
      • Properties:常用来处理配置文件。

Collection接口继承树
在这里插入图片描述
Map接口继承树
在这里插入图片描述

Collection接口的常用方法

package com.pan;

import org.junit.Test;

import java.util.*;

class Person{
    String name;
    int age;

    public Person() {
    }

    public String getName() {
        return name;
    }

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

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

    public int getAge() {
        return age;
    }

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

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    //按照姓名从小到大排序
    @Override
    public int compareTo(Object o) {
        if(o instanceof Person){
            Person p = (Person)o;
            int compare = this.name.compareTo(p.name);
            if(compare != 0){
                return compare;
            }
            else{
                return Integer.compare(this.age,p.age);
            }
        }
        else{
            throw new RuntimeException("输入类型不匹配");
        }
    }
}

public class CollectionTest {
    @Test
    public void test1(){
        Collection coll = new ArrayList();
        //add(Object e):将元素添加到coll中
        coll.add("aa");
        coll.add("ss");
        coll.add(233);
        coll.add(new Date());
        System.out.println(coll.size());//4

        Collection coll1 = new ArrayList();
        coll1.add(456);
        coll.addAll(coll1);
        System.out.println(coll.size());//5
        System.out.println(coll);//[aa, ss, 233, Fri Aug 13 16:41:37 GMT+08:00 2021, 456]

        System.out.println(coll.isEmpty());//false
        coll.clear();
        System.out.println(coll.isEmpty());//true
    }

    @Test
    public void test2(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(456);
        coll.add(false);
        coll.add(new Person("Jerry",10));

        //contains(Object obj):判断当前集合中是否包含obj,判断时调用obj对象所在类的equals(),如果是自定义类,那么重写equals方法
        boolean contains = coll.contains(123);
        System.out.println(contains);//true
        System.out.println(coll.contains(new String("Tom")));//true,String重写了equals()方法
        System.out.println(coll.contains(new Person("jerry",10)));
//        Person equals...
//        Person equals...
//        Person equals...
//        Person equals...
//        Person equals...
//        false
        //remove(Object obj):从当前集合中移除obj元素
        coll.remove(123);
        System.out.println(coll);//[Tom, 456, false, Person{name='Jerry', age=10}]
        System.out.println("*************************");
        coll.remove(new Person("Jerry",10));
        System.out.println(coll);
//        Person equals...
//        Person equals...
//        Person equals...
//        Person equals...
//        [Tom, 456, false]

        //removeAll(Collecction coll1):从当前集合中移除coll1中所有的元素(移除交集)
        Collection coll1 = Arrays.asList(123,456);
        coll.removeAll(coll1);
        System.out.println(coll);//[Tom, false]

    }
    @Test
    public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(456);
        coll.add(new Person("Jerry",10));

        //retainAll(Collection coll1):保留当前集合和coll1的交集
        Collection coll1 = Arrays.asList(123,456,789);
        coll.retainAll(coll1);
        System.out.println(coll);
//        Person equals...
//        Person equals...
//        Person equals...
//        [123, 456]

        //equals(Object obj):要想返回true,需要当前集合和形参(是一个集合)的元素都相同
        // 且如果是ArrayList还需要顺序相同

    }
    @Test
    public void test4(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(456);
        coll.add(new Person("Jerry",10));

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

        //toArray():集合---》数组
        Object[] objects = coll.toArray();
        for(int i = 0; i < objects.length;i++){
            System.out.println(objects[i]);
//            123
//            Tom
//            false
//            456
//            Person{name='Jerry', age=10}

        }
        //数组---》集合:调用Arrays类的静态方法asList()
        List<String> list = Arrays.asList(new String[]{"aa","bb","cc"});
        System.out.println(list);//[aa, bb, cc]
    }
}

使用迭代器和remove删除集合中的数据

package com.pan;

import org.junit.Test;

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

public class IteratorTest {
    //使用迭代器和remove删除集合中的数据
    @Test
    public void test1(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(456);
        coll.add(new Person("Jerry",10));

        Iterator iterator = coll.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            if("Tom".equals(obj)){
                iterator.remove();
            }
        }
        Iterator iterator1 = coll.iterator();
        while(iterator1.hasNext()) {
            System.out.println(iterator1.next());
//            123
//            false
//            456
//            Person{name='Jerry', age=10}
        }
    }
}

List接口中的常用方法

@Test
    public void test5(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Ton",23));
        list.add(123);
        System.out.println(list);//[123, 456, AA, Person{name='Ton', age=23}, 123]

        //void add(int index,Object ele):在index位置插入ele元素
        list.add(1,"BB");
        System.out.println(list);//[123, BB, 456, AA, Person{name='Ton', age=23}, 123]

        //boolean addAll(int index, Collection eles):从index位置开始将eles中所有元素加入list中
        List list1 = Arrays.asList(1,2);
        list.addAll(list1);
        System.out.println(list);//[123, BB, 456, AA, Person{name='Ton', age=23}, 123, 1, 2]

        //Object get(int index):获取指定index位置的元素
        System.out.println(list.get(2));//456

        //int indexOf(Object obj):返回obj在集合中首次出现的位置,如果不存在返回-1
        int index = list.indexOf(456);
        System.out.println(index);//2
        System.out.println(list.indexOf(888));//-1

        //int lastIndexOf(Object obj):返回obj在集合中最后出现的位置
        System.out.println(list.lastIndexOf("AA"));//3

        //Object remove(int index):移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);
        System.out.println(list);//[BB, 456, AA, Person{name='Ton', age=23}, 123, 1, 2]
        System.out.println(obj);//123

        //Object set(int index, Object ele):设置指定index位置的元素为ele,并返回被修改了的元素
        Object obj1 = list.set(1,444);
        System.out.println(list);//[BB, 444, AA, Person{name='Ton', age=23}, 123, 1, 2]
        System.out.println(obj1);//456

        //List subList(int fronIndex, int toIndex):返回从fromIndex到toIndex位置的子集合,左闭右开
        List subLsit = list.subList(1,4);
        System.out.println(subLsit);//[444, AA, Person{name='Ton', age=23}]
    }

Set集合

set:存储是无序的,不可重复的数据

  • 无序性:存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值来添加的。
  • 不可重复性

HashSet

添加元素的过程:
向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:

  • 如果此位置上没有其他元素,则元素a添加成功
  • 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
    • 如果hash值不相同,则元素a添加成功。
    • 如果hash值相同,进而需要调用元素a所在类的equals()方法:
      • equals()返回true,元素a添加失败
      • equals()返回false,则元素a添加成功

说明:对于添加成功的情况,元素a于已经存在的指定索引位置上的数据以链表方式存储。
HashSet存储示例图:
在这里插入图片描述

@Test
    public void test1(){
        Set set = new HashSet();
        set.add(456);
        set.add(123);
        set.add("AA");
        set.add("Pan");
        set.add(new Person("Jerry",20));
        set.add(new Person("Jerry",20));//Person类需要重写equals方法和hashCode方法才能判断这两个是相等的
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() + " ");
        }//AA 456 123 Pan Person{name='Jerry', age=20}
        System.out.println(set.add(123));//false
    }

LinkedHashSet

在这里插入图片描述
参考

@Test
    public void test2(){
        Set set = new LinkedHashSet();
        set.add(456);
        set.add(123);
        set.add("AA");
        set.add("Pan");
        set.add(new Person("Jerry",20));
        set.add(new Person("Jerry",20));//Person类需要重写equals方法和hashCode方法才能判断这两个是相等的
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() + " ");
        }//456 123 AA Pan Person{name='Jerry', age=20}
        System.out.println(set.add(123));//false
    }

TreeSet

  • 向TreeSet中添加的数据,要求是相同类的对象

TreeSet的自然排序

Person类中需要重写以下方法:

//按照姓名从小到大排序
    @Override
    public int compareTo(Object o) {
        if(o instanceof Person){
            Person p = (Person)o;
            int compare = this.name.compareTo(p.name);
            if(compare != 0){
                return compare;
            }
            else{
                return Integer.compare(this.age,p.age);
            }
        }
        else{
            throw new RuntimeException("输入类型不匹配");
        }
    }
@Test
    public void test3(){
        TreeSet tree = new TreeSet();
        TreeSet tree1 = new TreeSet();

        /*tree.add(123);//错误用法
        tree.add(456);
        tree.add("pan");
        tree.add(new Person("zhou",23));*/

        tree.add(34);
        tree.add(-35);
        tree.add(789);
        tree.add(45);
        Iterator iterator = tree.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() + " ");//-35 34 45 789
        }

        System.out.println();
        tree1.add(new Person("Jerry",12));
        tree1.add(new Person("Tom",17));
        tree1.add(new Person("Alicy",18));
        tree1.add(new Person("Pan",25));
        tree1.add(new Person("Zhou",26));
        tree1.add(new Person("Jerry",23));
        Iterator iterator1 = tree1.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
//        Person{name='Alicy', age=18}
//        Person{name='Jerry', age=12}
//        Person{name='Jerry', age=23}
//        Person{name='Pan', age=25}
//        Person{name='Tom', age=17}
//        Person{name='Zhou', age=26}
    }

TreeSet的定制排序

@Test
    public void test4() {
        //按照年龄从大到小排列
        Comparator com = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Person && o2 instanceof Person) {
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    int a = -1 * Integer.compare(p1.getAge(), p2.getAge());
                    if(a != 0){
                        return a;
                    }
                    else{
                        return ((Person) o1).name.compareTo(((Person) o2).name);
                    }

                } else {
                    throw new RuntimeException("输入的数据类型不匹配");
                }
            }
        };
        TreeSet tree1 = new TreeSet(com);
        tree1.add(new Person("Jerry",12));
        tree1.add(new Person("Tom",17));
        tree1.add(new Person("Alicy",18));
        tree1.add(new Person("Pan",25));
        tree1.add(new Person("Zhou",23));
        tree1.add(new Person("Jerry",23));
        Iterator iterator1 = tree1.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
    }

Map

在这里插入图片描述
Map中的key:无序的,不可重复的,使用Set存储所有的key,key所在的类要重写equals()和hashCode()(以HashMap为例)。
Map中的value:无序的,可重复的,使用Collection存储所有的value,value所在类要重写equals()。
一个键值对:key-value构成了一个Entry对象。
Map中的entry:无序的,不可重复的,使用Set存储所有的entry。

参考视频
在这里插入图片描述
HashMap的底层实现原理:
HashMap map = new HashMap();
首次调用put()方法时,底层创建长度为16的数组
…可能已经执行了多次put…
map.put(key1,value1):
首先,调用key1所在类的hashCode()方法计算key1的哈希值,此哈希值经过某种算法计算以后,得到在Node[]数组中的存放位置

  • 如果此位置上的数据为空,此时的key1-value1添加成功。
  • 如果此位置上的数据不为空,(意味着此位置上存在一个或者多个数据(以链表形式存在)),比较key1和已经存在的一个和多个数据的哈希值:
    • 如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。
    • 如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)
      • 如果equals返回false:此时key1-value1添加成功。
      • 如果equals返回false:使用value1替换value2
        jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
        当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组长度>64时,此时此索引位置上的所有数据改为使用红黑树存储。

HashMap

@Test
    public void test1(){
        Map map = new HashMap();
        //添加
        map.put("AA",213);
        map.put("Pan",234);
        map.put("CC","rr");
        map.put(23,54);
        //修改
        map.put("AA",89);
        System.out.println(map);//{AA=89, CC=rr, 23=54, Pan=234}

        Map map1 = new HashMap();
        map1.put("Zhou",34);
        map1.putAll(map);
        System.out.println(map1);//{AA=89, CC=rr, 23=54, Pan=234, Zhou=34}

        //remove(Object key)
        Object value = map.remove("CC");
        System.out.println(value);//rr
        System.out.println(map);//{AA=89, 23=54, Pan=234}


    }
    /*元素查询的操作:
    * Object get(Object key):获取指定key对应的value
    * boolean containsKey(Object key):是否包含指定的key
    * boolean containsValue(Object value):是否包含指定的value
    * int size():返回map中key-value对的个数
    * boolean isEmpty():
    * boolean equals(Object obj):判断当前map和参数对象obj是否相等
    * */
    @Test
    public void test2(){
        Map map = new HashMap();
        map.put("AA",213);
        map.put("Pan",234);
        map.put("CC","rr");
        map.put(23,54);
        System.out.println(map.get(23));//54
        System.out.println(map.get(455));//null

        boolean cc = map.containsKey("CC");
        System.out.println(cc);//true
        boolean gg = map.containsKey("gg");
        System.out.println(gg);//false

        boolean b = map.containsValue(213);
        System.out.println(b);//true
        boolean b1 = map.containsValue(555);
        System.out.println(b1);//false

        Map map1 = new HashMap();
        map1.put("AA",213);
        map1.put("Pan",234);
        map1.put("CC","rr");
        map1.put(23,54);
        System.out.println(map.equals(map1));//true
    }
    /*元视图操作的方法:
    *Set keySet():返回所有key构成的Set集合
    * Collection values():返回所有value构成的Collection集合
    * Set entrySet():返回所有key-value对构成得Set集合
    * */
    @Test
    public void test3(){
        Map map = new HashMap();
        map.put("AA",213);
        map.put("Pan",234);
        map.put("CC","rr");
        map.put(23,54);

        //遍历所有的key:keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() + " ");
        }//AA CC 23 Pan

        System.out.println();
        //遍历所有value:values()
        Collection values = map.values();
        for(Object obj : values){
            System.out.print(obj + " ");
        }//213 rr 54 234

        System.out.println();
        //遍历所有的key-value:entrySet()
        Set set1 = map.entrySet();
        Iterator iterator1 = set1.iterator();
        while(iterator1.hasNext()){
            Object next = iterator1.next();
            Map.Entry entry = (Map.Entry)next;
            System.out.println(entry.getKey() + "-->" + entry.getValue());
        }
//        AA-->213
//        CC-->rr
//        23-->54
//        Pan-->234
    }

TreeMap

TreeMap自然排序

@Test
    public void test4(){
        TreeMap map = new TreeMap();
        Person p1 = new Person("Tom",23);
        Person p2 = new Person("Jerry",34);;
        Person p3 = new Person("pan",21);
        Person p4 = new Person("zhou",21);
        Person p5 = new Person("Li",54);

        map.put(p1,34);
        map.put(p2,36);
        map.put(p3,56);
        map.put(p4,89);
        map.put(p5,21);
        Set set1 = map.entrySet();
        Iterator iterator1 = set1.iterator();
        while(iterator1.hasNext()){
            Object next = iterator1.next();
            Map.Entry entry = (Map.Entry)next;
            System.out.println(entry.getKey() + "-->" + entry.getValue());
        }
//        Person{name='Jerry', age=34}-->36
//        Person{name='Li', age=54}-->21
//        Person{name='Tom', age=23}-->34
//        Person{name='pan', age=21}-->56
//        Person{name='zhou', age=21}-->89
    }

TreeMap定制排序

//TreeMap定制排序:按年龄从大到小
    @Test
    public void test5(){
        TreeMap map = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Person && o2 instanceof Person){
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    return -1*Integer.compare(p1.getAge(),p2.getAge());
                }
                throw new RuntimeException("输入类型不匹配");
            }
        });
        Person p1 = new Person("Tom",23);
        Person p2 = new Person("Jerry",34);;
        Person p3 = new Person("pan",21);
        Person p4 = new Person("zhou",21);
        Person p5 = new Person("Li",54);

        map.put(p1,34);
        map.put(p2,36);
        map.put(p3,56);
        map.put(p4,89);
        map.put(p5,21);
        Set set1 = map.entrySet();
        Iterator iterator1 = set1.iterator();
        while(iterator1.hasNext()){
            Object next = iterator1.next();
            Map.Entry entry = (Map.Entry)next;
            System.out.println(entry.getKey() + "-->" + entry.getValue());
        }
    }
//    Person{name='Li', age=54}-->21
//    Person{name='Jerry', age=34}-->36
//    Person{name='Tom', age=23}-->34
//    Person{name='pan', age=21}-->89

Collections工具类

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

/*
    * 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):根据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 oldVal,Object newVal):使用新值替换List对象的所有旧值
    * */
    @Test
    public void test6(){
        List list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add(456);
        list.add(78);
        list.add(-65);
        list.add(0);
        list.add(1);
        System.out.println(list);

//        Collections.reverse(list);
//        Collections.shuffle(list);
//        Collections.sort(list);
//        Collections.swap(list,1,2);
//        int frequency = Collections.frequency(list, 456);

//        System.out.println(list);

        List list1 = Arrays.asList(new Object[list.size()]);
        System.out.println(list1);//[null, null, null, null, null, null, null]
        Collections.copy(list1,list);
        System.out.println(list1);//[123, 456, 456, 78, -65, 0, 1]
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pk5515

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值