Java基础之集合

1.集合的概述

1.1相关概念

  1. 集合、数组都是对多个数据进行存储操作的结构,简称java容器(说明:此时的存储,主要是指内存方面的存储,不涉及持久化的存储比如数据库、txt文件)
  2. 数组在存储多个数据结构方面的优点
  • 一旦初始化后,长度就确定了
  • 数组一旦定义好,其元素的类型也就确定了,我们只能操作指定类型的数据
  1. 数组的存在多个数据结构方面的缺点
  • 一旦初始化后,其长度不可修改
  • 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高
  • 获取数组中实际元素个数的需求,数组没有现成的属性和方法可用
  • 数组存在数据的特点:有序、可重复。对于无序、不可重复的需求不能满足

1.2Java集合的分类

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

  1. Collection接口:单列数据,定义了一组存储数据方法的集合
  • List:元素有序、可重复的集合(LLinkedList、ArrayList,Vector)
  • Set:元素无序,不可重复的集合(HashSet、LinkHashSet、TreeSet)
    在这里插入图片描述
  1. Map接口
  • 双列数据,保存具有映射关系"key-value对"集合(HashMap、LinkedHaspMap、TreeMap、HashTable、Properties)
    在这里插入图片描述

2.Collection

2.1接口方法

  1. 添加
    add(Object obj)
    addAll(Collection coll)
  2. 获取有效元素的个数
    int size()
  3. 清空集合
    void clear()
  4. 是否是空集合 boolean isEmpty()
  5. 是否包含某个元素
    boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
    boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。
  6. 删除
    boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
    boolean removeAll(Collection coll):取当前集合的差集
  7. 取两个集合的交集
    boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
  8. 集合是否相等
    boolean equals(Object obj)
  9. 转成对象数组
    Object[] toArray()
  10. 获取集合对象的哈希值
    hashCode()
  11. 遍历
    iterator():返回迭代器对象,用于集合遍历
    举例
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        collection.add("11");//添加元素
        collection.add("22");
        collection.add("33");
        System.out.println(collection.size());//获取有效元素的个数
        System.out.println(collection.isEmpty());//是否为空
        System.out.println(collection.contains("11"));//是否包含某个元素
        collection.remove("11");//:通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
        System.out.println("==========================");
        for(Object o:collection)
        {
            System.out.println(o);
        }
        String s = collection.toString();
        System.out.println(s);
        Object[] objects = collection.toArray();//转化为数组
        System.out.println("==================================");
        for(Object o:objects)
        {
            System.out.println(o);
        }
        System.out.println("========================");
        ArrayList<Object> objects1 = new ArrayList<>();
        objects1.add("22");
        collection.removeAll(objects1);//当前集合的差集
        for(Object o:collection)
        {
            System.out.println(o);
        }
        collection.add("22");
        System.out.println("=====================");
        boolean b = collection.retainAll(objects1);//获取两个集合的交集
//        System.out.println(b);
        for(Object o:collection)
        {
            System.out.println(o);
        }
        System.out.println(collection.equals(objects1));//判断两个集合是否相等
        
    }

3.Iterator迭代器接口

3.1使用 Iterator 接口遍历集合元素

  1. Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
  2. GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。
  3. Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
  4. Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
  5. 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

3.2Iterator接口的方法

  1. 使用next()获得序列中的下一个元素。
  2. 使用hasNext()检查序列中是否还有元素。
  3. 使用remove()将迭代器新返回的元素删除。
 public static void main(String[] args) {
        ArrayList<Object> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        Iterator<Object> iterator = arrayList.iterator();
        //遍历方式一
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println("================================");
        iterator= arrayList.iterator();
        //遍历方式二
        for(int i=0;i<arrayList.size();i++)
        {
            System.out.println(iterator.next());
        }

        iterator=arrayList.iterator();
        System.out.println("================================");
        //遍历方式三
        while (iterator.hasNext())//判断是否有下一个元素
        {
        //next():①指针下移 ②将下移以后集合位置上的元素返回
            System.out.println(iterator.next());
        }
    }

remove的使用

   @Test
    public void tes1(){
       ArrayList<Object> arrayList = new ArrayList<>();
       arrayList.add(1);
       arrayList.add(2);
       arrayList.add(3);
       Iterator<Object> iterator = arrayList.iterator();
       while(iterator.hasNext())
       {
           int next = (int)iterator.next();
           if(next==1)
           {
               iterator.remove();
           }
       }
       iterator=arrayList.iterator();
       while(iterator.hasNext())
       {
           System.out.println(iterator.next());
       }
   }

注意:

  • Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方 法,不是集合对象的remove方法。
  • 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。

3.3使用 foreach 循环遍历集合元素

  1. Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
  2. 遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
  3. 遍历集合的底层调用Iterator完成操作。
  4. foreach还可以用来遍历数组。
  5. 修改遍历结果不会改变原来的值
//for(集合元素的类型 局部变量:集合对象) 内部仍调用迭代器
   @Test
    public void text2()
   {
       ArrayList<Object> arrayList = new ArrayList<>();
       arrayList.add(1);
       arrayList.add(2);
       arrayList.add(3);
       for(Object x:arrayList)
       {
           System.out.println(x);
       }
   }

4.List接口

4.1List接口的概述

  • collocation接口:单列集合用来存储一个个对象
  • List接口:存储有序的可重复的数据,动态数组,代替原有的数组
  • list接口有:ArrayList,LinkedList和vector

4.2ArrayList,LinkedList和vectors三者的异同

同:三个都实现了List接口,存储数据的特点相同:存储有序可重复的数据
不同:

  • ArrayList作为List的主要实现类,线程不安全,效率高。底层使用Object[] elementData存储
  • LinkedList:对应频繁的插入和删除操作,效率都比ArrayList高,底层使用双向链表存储
  • vector:作为List接口的古老实现类,线程安全、效率低、底层使用Object[] elementData存储

4.3ArrayList源码分析

  1. jdk7以下
    底层创建一个长度为10的Object[] elementData数组,使用add向数组中添加元素,如果添加元素导致底层Object[] elementData数组容量不够,则扩容,默认情况下扩容到原来的1.5倍,同时将数据原有的数据赋值到新数组中,建议开发中使用带参的构造器 ArrayList lsit=new ArrayList(int capacity)
  2. jdk8中ArrrayList的变化
    底层Object[] elementData数组初始化为{}并没有创建长度第一次调用add()时,底层才创建了长度为10的数组,并将数据添加到elementData中,后面的添加和扩容操作与jdk7 无异
    小结:jdk7中ArrayList对象的创建类似于单例模式的饿汉式模式,而jdk8中ArrayList对象的创建类似于单例模式的懒汉式模式,延迟数组的创建,节省内存

4.4LinkList

采用链表的形式来存储数据

4.5List接口常用方法

方法名说明
void add(int index, Object ele)在index位置插入ele元素
boolean addAll(int index, Collection eles)从index位置开始将eles中的所有元素添加进来
Object get(int index)获取指定index位置的元素
int indexOf(Object obj)返回obj在集合中首次出现的位置
int lastIndexOf(Object obj)返回obj在当前集合中末次出现的位置
Object remove(int index)移除指定index位置的元素,并返回此元素
Object set(int index, Object ele)设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex)返回从fromIndex到toIndex位置的子集合
@Test
    public void test3()
   {
       ArrayList<Object> list = new ArrayList<>();
       list.add(1);//增
       list.add(2);
       list.add(3);
       //差
       for(int i=0;i<list.size();i++)
       {
           System.out.println(list.get(i));
       }
       list.remove(2);//通过下标删除
       System.out.println("=====================");
       for(Object o:list)
       {
           System.out.println(o);
       }
       list.set(0,10);//改
       System.out.println("======================");
       for(Object o:list)
       {
           System.out.println(o);
       }
       list.remove(new Integer(10));//通过值删除
       System.out.println("=======================");
       for(Object o:list)
       {
           System.out.println(o);
       }
   }

LinkList新增方法
void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()

4.6vector

在创建对象时,底层都创建了长度为10的数组,扩容时,扩大到原来的2倍

5 set接口

5.1set接口的概述

  • set接口:存储无序,不可重复的数据
    以Hashset为例说明:
  1. 无序性:不等于随机性,存储的数据在底层数组中并非按照数组的索引的顺序添加,而是根据数据的哈希值
  2. 不可重复性:保证添加的元素按照equals()判断时,不能返回true,即:相同的元素。只能添加一个
  • Hashset:作为set接口的主要实现类,线程不安全,可以存储null值
  • LinkedHashSet:作为HashSet子类,遍历其内部数据时,可以按照添加顺序遍历
  • TreeSet:可以按照添加对象属性进行排序,采用了红黑树的方式进行存储
  1. HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
  2. 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”

5.1.1向HashSet中添加元素的过程

HashSet特点

  1. HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
  2. HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
  3. HashSet 具有以下特点:
  • 不能保证元素的排列顺序
  • HashSet 不是线程安全的
  • 集合元素可以是 null
  • 4.HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。

当向 HashSet 集合中存入一个元素a时,HashSet 会调用该对象的 hashCode() 方法来得到该对象a的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象在 HashSet 底层数组中的存储位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布,该散列函数设计的越好)
如果两个元素a,b的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。
如果两个元素a,b的hashcode()不相等,添加成功
jdk7:元素a放在数组中,指向原来的元素
jdk8:原来的元素在数组中,指向元素a
总结:7上8下
Hashset底层:数组+链表(数组初始容量为16,当如果使用率超过0.75,就会扩大容量为原来的2倍。
如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。

5.1.2重写 hashCode() 方法的基本原则

  • 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。
  • 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。
  • 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

5.2LinkedHashSet的使用

LinkedHashSet作为HashSet子类, 在添加数据的同时,每个数据还维护了两个引用,记录此数据的前一个数据和后一个数据
优点:对于频繁的遍历操作,LinkedHashSet更方便

   @Test
    public void test4()
   {
       HashSet<Object> hashSet = new LinkedHashSet<>();
       hashSet.add(1);
       hashSet.add(3);
       hashSet.add(1);
       hashSet.add("hollow word");
       hashSet.add("hi");
       for(Object o:hashSet)
       {
           System.out.println(o);
       }
   }

5.3TreeSet

  1. 向TreeSet中添加的数据,要求是相同类的对象
  2. 两种排序方式:自然排序和定制排序(comparator)
  3. 在自然排序中,比较两个对象是否相等的标准为compareTo返回0而不是equals
    自然排序
public class People implements  Comparable{


    private String name;

    private int age;

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

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

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public int compareTo(Object o) {
        if(o instanceof People)
        {
            People o1 = (People) o;
            if(this.getAge()!=o1.getAge())
            {
                return this.getAge()<o1.getAge()?1:-1;
            }
            else
            {
                return this.getName().compareTo(o1.getName());
            }
        }
        return 0;
    }
}
   @Test
    public void test5(){
       TreeSet<People> treeSet = new TreeSet<>();
       treeSet.add(new People("zhangsan",19));
       treeSet.add(new People("zhangsan",90));
       treeSet.add(new People("lisi",23));
       treeSet.add(new People("wangqiang",44));
       treeSet.add(new People("aa",35));
       Iterator<People> iterator = treeSet.iterator();
       while (iterator.hasNext())
       {
           System.out.println(iterator.next());
       }
   }

定制排序

@Test
    public void text6()
   {
       Comparator comparator = new Comparator(){
           @Override
           public int compare(Object o1, Object o2) {
               if(o1 instanceof  People && o2 instanceof  People) {
                      People p1=(People) o1;
                   People p2=(People) o2;
                   if(p1.getAge()!=p2.getAge())
                   {
                       return p1.getAge()>p2.getAge()?1:-1;
                   }
                   else
                       return p1.getName().compareTo(p2.getName());
               }
               return 0;
           }
       };
       TreeSet treeSet = new TreeSet<>(comparator);
       treeSet.add(new People("zhangsan",19));
       treeSet.add(new People("zhangsan",90));
       treeSet.add(new People("lisi",23));
       treeSet.add(new People("wangqiang",44));
       treeSet.add(new People("aa",35));
       Iterator iterator = treeSet.iterator();
       while (iterator.hasNext())
       {
           System.out.println(iterator.next());
       }
   }

经典例题

public class Person {
    private int id;
    private String name;

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

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

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Person() {
    }

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


   @Test
    public void test7()
   {
       HashSet set = new HashSet();
       Person p1 = new Person(1001,"AA");
       Person p2 = new Person(1002,"BB");
       set.add(p1);
       set.add(p2);
       System.out.println(set);
       p1.setName("CC");
       set.remove(p1);
       System.out.println(set);
       System.out.println("=================");
       set.add(new Person(1001,"CC"));
       System.out.println(set);
       System.out.println("================");
       set.add(new Person(1001,"AA"));
       System.out.println(set);
   }

6. Map接口

6.1Map接口的概述

  1. Map与Collection并列存在。用于保存具有映射关系的数据:key-value
  2. Map 中的 key 和 value 都可以是任何引用类型的数据
  3. Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法
  4. 常用String类作为Map的“键”
  5. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
  6. Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类
    在这里插入图片描述

6.1 Map实现类结构

  1. Map:双列数据,存储key-value对的数据,类似于高中的函数
  2. HashMap:作为Map的主要实现类,线程不安全,效率高,可以存储null的key和value
  • LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现(在原因的hashMap底层结果基础上,添加一对指针,指向前一个和后一个元素,对于频繁的遍历操作,此执行效率高于HashMap)
  1. TreeMap: 保证按照添加的key-value;对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序,底层使用红黑树
  2. HashTable:作为古老的实现类,线程安全,效率低,不能存储null的key和value
  • properties:常用来处理配置文件,key和value都是Sting类型

HashMap的底层:

  • jdk7及以前:数组+链表
  • jdk8 数组+链表+红黑树

面试题:
HashMap底层实现原理
HashMap和HashTable区别

6.2Map结构的理解

  • Map中的key:无序,不可重复,使用set存储所有的key(key所在的类要重写equals和hashCode方法)
  • Map中的value:无序,可重复,使用Collection存储所有的value(value所在的类要重写equals)
  • 一个键值对:key-value构成一个entry对象
  • Map中的entry:无序不可重复,使用set存储所有的entry

6.3 Has和Map底层实现原理,以jdk7为例

HashMap的内部存储结构其实是数组和链表的结合。
HashMap<Object, Object> map = new HashMap<>();实例化以后,底层创建一个长度为16的Entry[] table数组向HashMap中添加entry1(key,value),需要首先计算entry1中key的哈希值(根据key所在类的hashCode()计算得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i。如果位置i上没有元素,则entry1直接添加成功。如果位置i上已经存在entry2(或还有链表存在的entry3,entry4),则需要通过循环的方法,依次比较entry1中key和其他的entry。如果彼此hash值不同,则直接添加成功(和原来的数据用链表的形式进行存储)。如果hash值不同,继续比较二者是否equals。如果返回值为true,则使用entry1的value去替换equals为true的entry的value。如果遍历一遍以后,发现所有的equals返回都为false,则entry1仍可添加成功(和原来的数据用链表的形式进行存储)。entry1指向原有的entry元素。
在不断添加的过程中会涉及到扩容问题,当超出临界值(且要存放的位置非空时),扩容,默认扩容到原来两倍,然后重新计算每个元素在数组中的位置
jdk8相较于jdk7底层实现方面的不同

  1. new HashMap()底层没有创建长度为16的数组
  2. jdk 8地磁场数组是Node[]而非Entry[]
  3. 首次调用put方法是,底层创建长度为16的数组
  4. jdk7的底层只有数组+链表,而jdk8底层是数组+链表+红黑树(当数组某个位置上的元素以链表的形式存在数据的个数》8且当前数组的个数大于64时,此时索引位置上所有数据改为红黑树存储)

HashMap源码中的重要常量

  • DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
  • MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30
  • DEFAULT_LOAD_FACTOR:HashMap的默认加载因子 0.75
  • THRESHOLD:扩充的临界值=容量+扩充因子 16*0.75 >=12
  • TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树
  • UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
  • MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。

6.4LinkHashMap底层原理

  • LinkedHashMap 是 HashMap 的子类
  • 在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

6.5Map常用方法

  1. 添加、删除、修改操作:
  • 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中的所有数据
  1. 元素查询的操作:
  • Object get(Object key):获取指定key对应的value
  • boolean containsKey(Object key):是否包含指定的key
  • boolean containsValue(Object value):是否包含指定的value
  • int size():返回map中key-value对的个数
  • boolean isEmpty():判断当前map是否为空
  • boolean equals(Object obj):判断当前map和参数对象obj是否相等
  1. 元视图操作的方法:
  • Set keySet():返回所有key构成的Set集合
  • Collection values():返回所有value构成的Collection集合
  • Set entrySet():返回所有key-value对构成的Set集合
    常用方法:添加,修改,删除,查询,长度
   @Test
    public void text8()
   {
       HashMap<Object, Object> hashMap = new HashMap<>();
       //添加
       hashMap.put("a",1);
       hashMap.put("b",2);
       hashMap.put("c",4);
       System.out.println(hashMap);
       //修改
       hashMap.put("a",11);
       System.out.println(hashMap);
       //删除
       Object a = hashMap.remove("a");
       System.out.println(a);
       Object d = hashMap.remove("d");
       //删除数据不存在
       System.out.println(d);
       System.out.println(hashMap);
       //map大小
       System.out.println(hashMap.size());
       //是否为空
       System.out.println(hashMap.isEmpty());
       //是否包含指定的key
       System.out.println(hashMap.containsKey("b"));
       //是否包含指定的value
       System.out.println(hashMap.containsValue(2));
       //返回所要key的set集合
       Set<Object> keySet = hashMap.keySet();
       System.out.println("所有的key");
       for(Object k:keySet)
       {
           System.out.println(k);
       }
       System.out.println("所有的value");
       //返回所要的vaule
       Collection<Object> values = hashMap.values();
       for(Object o:values)
       {
           System.out.println(o);
       }
       System.out.println("key-value");
       //获取所有的key-value
       //方式一
       Set<Map.Entry<Object, Object>> entries = hashMap.entrySet();
       Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();
       while(iterator.hasNext())
       {
           Map.Entry<Object, Object> next = iterator.next();
           System.out.println(next.getKey()+"----->"+next.getValue());
       }
       //方式二
       for(Object o:keySet)
       {
           System.out.println(o+"-------------->>>"+hashMap.get(o));
       }
   }

6.6TreeMap排序

自然排序
person.java

package com.blb.com;

import java.util.Objects;

/**
 * @author smilecb
 * @date 2021/9/12 0012 11:22
 */
public class Person implements Comparable{
    private int id;
    private String name;

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

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

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Person() {
    }

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

    @Override
    public int compareTo(Object o) {
        if(o instanceof  Person)
        {
            Person p=(Person) o;
            if(this.getId()!=p.getId())
            {
                return this.getId()<p.id?1:-1;
            }
            else
            {
                return this.getName().compareTo(p.getName());
            }
        }
        return 0;
    }
}

测试类

   @Test
    public void text9()
   {
       TreeMap treeMap = new TreeMap<>();
       treeMap.put(new Person(1,"shangsan"),70);
       treeMap.put(new Person(3,"lisi"),60);
       treeMap.put(new Person(1,"wangwu"),80);
       treeMap.put(new Person(2,"cb"),66);
       Set set = treeMap.keySet();
       Iterator iterator = set.iterator();
       while (iterator.hasNext())
       {
           Object next = iterator.next();
           System.out.println(next+"---->"+treeMap.get(next));
       }
   }

定制排序

@Test
   public void text10()
   {
       Comparator<Object> objectComparator = 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;
                   if(!p1.getName().equals(p2.getName()))
                   return p1.getName().compareTo(p2.getName());
                   else
                       return p1.getId()-p2.getId();
               }
               return 0;
           }

       };
       TreeMap treeMap = new TreeMap<>(objectComparator);
       treeMap.put(new Person(1,"shangsan"),70);
       treeMap.put(new Person(3,"lisi"),60);
       treeMap.put(new Person(1,"wangwu"),80);
       treeMap.put(new Person(2,"lisi"),66);
       Set set = treeMap.keySet();
       Iterator iterator = set.iterator();
       while (iterator.hasNext())
       {
           Object next = iterator.next();
           System.out.println(next+"---->"+treeMap.get(next));
       }
   }

6.7HashMap和HashTable区别

  1. Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
  2. Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
  3. 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
  4. 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  5. Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。

6.8Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

7. Collections工具类

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

7.1Collection和Collections区别

Collection是一个接口,而Collections是操作Collection和Map一个工具类

7.2常用方法

方法名描述
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)根据 Comparator 指定的顺序,返回给定集合中的最小元素
int frequency(Collection,Object)返回指定集合中指定元素的出现次数
void copy(List dest,List src)将src中的内容复制到dest中 boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值

Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值