集合框架的使用

1.集合框架

1.1集合框架的概念

Java集合框架(Java Collections Framework简称JCF)是为表示和操作集合,而规定的一种统一的标准的体系结构。集合框架包含三大块内容:对外的接口、接口的实现和对集合运算的算法。集合就是用于存储对象的容器。 只要是对象类型就可以存进集合框架中。集合的长度是可变的。 集合中不可以存储基本数据类型的值。

1.2集合和数组的区别

数组和集合相比,数组的缺点是它长度是固定的,没有办法动态扩展。而集合存储数据时是没有长度限制的,是可以动态扩展的。集合容器因为内部的数据结构不同,有多种不同的容器对象。这些容器对象不断的向上抽取,就形成了集合框架。

1.3为什么使用集合

我们在java中学习过一个数据类型 --- 数组; 数组存在问题: 定容 (数组初始化的时候 一旦固定容量 从此就只能存储该容量的数据)如果我们一旦创建数组 发现数组的容量不够用了 此时就需要扩容就会非常麻烦。

1.4集合框架体系图

List接口及其实现类

1.4.1特点

  • List集合是有序集合: 数据的添加和存储次序一致
  • List集合可以存储重复的数据
  • List集合中的数据可以通过下标访问

返回类型

方法名称

描述

boolean

add(Object o)

在集合末尾添加元素

int

size()

返回集合列表中元素个数

Object

get(int index)

返回指定索引位置的元素,索引从0开始

boolean

removeAll(Collection col)

删除集合中的所有元素

boolean

contains(Object o)

判断集合中是否存在指定元素

boolean

remove(Object o)

从集合中删除元素

Object

remove(int index)

从集合中删除指定索引位置的元素

1.4.2ArrayList实现类

特点:

  • 实现了List接口
  • 可以动态扩容(我们只管存,长度不够,底层会自动的扩容)
  • 通过下标可以快速访问数据
  • 查找快,插入删除慢
  • ArrayList底层是数组,对数组做了封装
  • 可以存储任意类型的数据,包括null
  • 数据按照存储次序排列数据可以重复 
  • 多线程访问时不安全

1.4.3ArrayList的创建和使用

创建集合框架

List list = new ArrayList(); //创建一个集合对象 如果没有指定集合容器的长度默认为10
List list1 = new ArrayList(15);

添加元素

  /*添加元素操作,插入的值可以是任意类型*/
        list1.add("java01");
        list1.add("java02");
        list1.add("java03");
        list1.add(true);
        list1.add(new Date());
        list1.add(2,"hello");
        System.out.println(list1);
        list2.add("a");
        list2.add("b");
        list1.addAll(list2);//将list2中全部元素添加到list1中
        System.out.println(list2);

 删除元素

		list1.remove(2);//移除下标为2的元素
        System.out.println(list1);
        list1.clear();//清空集合中的元素.
        System.out.println(list1);

修改元素

		list1.set(1,"mm");//将下标为1设置为mm
        System.out.println(list1);

查找元素

/*查询操作*/
        Object o = list1.get(0);//根据下标获取元素
        System.out.println(o);
        int size = list1.size();//获得集合中元素的个数
        System.out.println(size);
        boolean f = list1.contains("java01");//判断集合中是否存在某个元素
        System.out.println(f);
        System.out.println(list1);
        int index = list1.indexOf("java02");//存在就返回第一次出现的位置否则返回-1
        System.out.println(index);
        /*遍历循环集合中的元素*/
        for (Object o2:list1){
            System.out.println(o2);
        }

1.4.4 ArrayList底层源码

从构造方法来入手
	new ArrayList(22) 底层声明了一个Object类型的数组 名字elementData
  	Object[] elementData
  	public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) { //大于0
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) { //等于初始化为一个空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else { //抛出一个异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

==========add("java01")======E理解为Object类型================  
   public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 扩容 
        elementData[size++] = e;  //把元素赋值给数组的相应位置
        return true;
    }
==========indexOf("java02") 判断元素在集合中第一次的位置=============
     public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i])) //和数组中的每个元素内容进行比对
                    return i;  //返回元素在集合中位置
        }
        return -1;
    }   

===========size() 请求数组的长度======================
 public int size() {
        return size;
    }   

============contain("java05")判断元素是否在集合中==============
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
===============get(1) 获取指定位置的元素========
   public E get(int index) {
        rangeCheck(index); //判断指定的位置是否合法 

        return elementData(index);
    }  

    E elementData(int index) {
        return (E) elementData[index];
    } 

============toString() 为什么不打印对象的引用地址 
    [java01, java02, java03, java02]因为重写了Object里面的toString方法。
    
 public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }   
    
    
通过对ArrayList方法的底层代码分析:底层就是对数组的操作。
    ArrayList的底层就是基于数组实现的。

1.5 LinkedList集合

     它是一个链表结构。 LinkedList: 具有List的特征,底层以链表结构实现,可以进行头尾元素的添加删除;

 1.5.1LinkedList与ArrayList的区别

    ArrayList  底层体现出来的数据结构是 数组
    Linkedlist 底层体现出来的数据结构是 链表
1.5.2 LinkedList的使用

添加操作

 	    LinkedList linkedList = new LinkedList();
        linkedList.add("java01");
        linkedList.addFirst("java02"); //添加到头部
        linkedList.addLast("java03");//追加到尾部
        linkedList.addFirst("java04"); //追加到头部
        linkedList.addLast("java05");//追加到尾部
        System.out.println(linkedList);

删除操作

		linkedList.removeFirst();//移除头部元素
        System.out.println(linkedList);
        linkedList.remove(2);//移除指定位置的元素
        System.out.println(linkedList);
        linkedList.removeLast();//移除尾部的元素
        System.out.println(linkedList);

 修改操作

linkedList.set(1,"java11");

 查询操作

 //查询操作
        int size = linkedList.size();//求长度
        boolean empty = linkedList.isEmpty();//是否为空
        boolean b = linkedList.contains("java01");//判断元素是否在集合中
        Object o = linkedList.get(1);//根据下标获取指定位置的元素
        Object first = linkedList.getFirst();//获取第一个元素
        System.out.println(first);
        Object last = linkedList.getLast();
        System.out.println(last);

1.5.3 LinkedList的底层源码。

1.凡是查询源码 ,我们都是从类的构造方法入手:
     /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }
 该类的构造方法内是空的,没有任何的代码。 但是该类中有三个属性。   
    transient int size = 0; //索引
   
    transient Node<E> first; //第一个元素对象 
   
    transient Node<E> last; //表示最后一个元素对象。
 
================ add的源码=====E:理解为Object类型==========================。
   public boolean add(E e) {
        linkLast(e);
        return true;
    }


   void linkLast(E e) {
        final Node<E> l = last;
        //上一个节点   数据  下一个节点
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    
==================Node的源码 内部类=======================================   
   private static class Node<E> { //<E>泛型--object
        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;
        }
    }
1、==================== get(1)-----获取元素========================
   public E get(int index) {
        checkElementIndex(index); //检查index下标是否正确。
        return node(index).item;  //李四Node对象
    }
 ========================node(index)=============================
 Node<E> node(int index) {
        //>> 位运算二进制运算 ----- size >> 1 一半的意思size/2
        if (index < (size >> 1)) { //前半部分
            Node<E> x = first; 
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {  //后半部分
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

 1.5.4LinkedList和ArrayList的区别

ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
• 随机访问效率:
ArrayList 比 LinkedList 在随机访问的时候效率要高,
因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
• 增加和删除效率:
在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,
因为 ArrayList 增删操作要影响数组内的其他数据的下标。
• 综合来说:
在需要频繁读取集合中的元素时,更推荐使用 ArrayList,
而在插入和删除操作较多时,更推荐使用 LinkedList

2.set集合

2.1 Set接口及实现类

2.2.1Set接口的特点

  • Set接口是无序的
  • Set接口中的数据不允许重复
  • Set接口无法通过下标访问数据
  • 查找慢,插入删除快(底层数据结构是哈希表和红黑树)
  • Set集合使用equals()和hashCode()方法实现元素去重

 2.2HashSet实现类

2.2.1HashSet特点

  • HashSet是Set接口的实现类
  • 线程不安全
public class Test02 {
    public static void main(String[] args) {
        HashSet  hashSet= new HashSet();

        HashSet  hashSet1 = new HashSet(16);//初始容器的大小

        //loadFactor:--->0.7f 表示负载因子 当空间使用70%时 要求扩容
        HashSet hashSet2 = new HashSet(16,0.7f);
    }
}

添加元素

//添加操作
        hashSet.add("java01");
        hashSet.add("java02");
        hashSet.add("java04");
        hashSet.add("java03");
        hashSet.add("java02");

        HashSet set2=new HashSet();
        set2.add("刘德华");
        set2.add("张学友");
        set2.add("黎明");
        
        hashSet.addAll(set2); //把set2中的每个元素添加到hashset中
        System.out.println(hashSet); //元素不能重复 而且无序

删除元素

     //删除
        hashSet.remove("黎明");
        hashSet.clear();//清空容器集合
        System.out.println(hashSet);

修改元素

   //修改操作
        boolean empty = hashSet.isEmpty(); //判断是否为空
        System.out.println(empty);

        boolean b = hashSet.contains("刘德华");//判断元素是否在容器中
        System.out.println(b);

遍历元素

(1)通过foreach遍历

 //遍历--- foreach
        for(Object o: hashSet){
            System.out.println(o);
        }

(2)通过迭代器来遍历

迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器对象(container,例如链表数组)上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节。HashSet类中没有提供根据集合索引获取索引对应的值的⽅法,因此遍历HashSet时需要使⽤Iterator迭代器。Iterator的主要⽅法如下

返回类型

方法

描述

boolean

hasNext()

如果有元素可迭代

Object

next()

返回迭代的下⼀个元素

 //迭代器遍历
        Iterator iterator = hashSet.iterator();//获取迭代器对象 有序:有下标
        while (iterator.hasNext()){//判断是否指定能够移动
            Object next = iterator.next();//指定移动并获取当前的元素
            System.out.println(next);
        }

2.2.2 hashSet的源码

从构造函数说起:
    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
    public HashSet() {
        map = new HashMap<>();
    }
 在创建一个HashSet的对象时,底层创建的是HashMap。我们说hashset的底层原理时,我们就在后HashMap的原理就行。 讲HashMap时给大家说原理。

2.3 TreeSet集合

TreeSet中的方法和HashSet中的方法一模一样 只是他们的实现不一样。
TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现

TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。

TreesSet特点:

  • 有序
  • 不重复
  • 添加、删除、判断元素存在性效率比较高
  • 线程不安全

存储String类型

TreeSet treeSet=new TreeSet();
        treeSet.add("java05");
        treeSet.add("java03");
        treeSet.add("java04");
        treeSet.add("java01");
        treeSet.add("java02");
        treeSet.add("java04");

        System.out.println(treeSet);

存储一个对象类型

public class Test04 {
    public static void main(String[] args) {
        TreeSet treeSet=new TreeSet();
        treeSet.add(new Student("王俊凯",17));
        treeSet.add(new Student("赵晓普",16));
        treeSet.add(new Student("赵俊涛",16));
        treeSet.add(new Student("闫克起",15));

        System.out.println(treeSet);
    }
}

通过运行我们发现出现如下的错误: TreeSet中的元素必须实现Comparable接口 方可放入TreeSet解决办法有两个:

第一个: 让你的类实现Comparable接口

package com.ykq;

import java.util.TreeSet;

/**
 * @program: day03
 * @description:
 * @author: 闫克起2
 * @create: 2022-04-16 15:59
 **/
public class Test04 {
    public static void main(String[] args) {
        TreeSet treeSet=new TreeSet(); //TreeSet不允许重复元素
        treeSet.add(new Student("王俊凯",17));
        treeSet.add(new Student("赵晓普",16));
        treeSet.add(new Student("赵俊涛",16));
        treeSet.add(new Student("闫克起",15));

        System.out.println(treeSet);
    }
}
class Student implements Comparable{
     private String name;
     private Integer age;

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

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

    public Student() {
    }

    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;
    }
   //排序:---返回如果大于0 表示当前元素比o大  如果返回-1 当前添加的元素比o小  返回0表示相同元素。
    @Override
    public int compareTo(Object o) {
        Student student= (Student) o;
        System.out.println(this+"===================>"+o);

        if(this.age>student.age){
            return 1;
        }
        if(this.age<student.age){
            return -1;
        }

        return 0;
    }
}

第二种: 在创建TreeSet时指定排序的对象。这种方法主要用到TreeSet集合中的带参构造
底层原理代码是:

public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

所以要实现Comparator接口,因此我们可以自定义类实现Comparator接口即可,具体代码如下:
Student类:

public class Student{
    String name;
    int age;

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

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

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

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

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

自定义类实现Comparator接口

public class MyComparator implements Comparator{

    @Override
    //原理与ComparableTo那个相同
    public int compare(Object o1, Object o2) {
        Student s1 = (Student)o1;
        Student s2 = (Student) o2;
        if (s1.getAge()>s2.getAge()){
            return 1;
        }else if(s1.getAge()<s2.getAge()){
            return -1;
        }
        return 0;
    }
}

测试类

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

        MyComparator myComparator = new MyComparator();
        TreeSet treeSet = new TreeSet(myComparator);

        treeSet.add(new Student("张三",18));
        treeSet.add(new Student("李四",17));
        treeSet.add(new Student("王五",19));
        treeSet.add(new Student("赵六",20));
        
        System.out.println(treeSet);
    }
}
注意:如果运行不起来记得看看导包是否错误

3. Map接口极其实现类

Map接口特点:

  • 以键值对方式存储数据(Collection是单值集合)
  • 键不能重复,键重复时,后面的数据会覆盖前面的数据
  • 可以存储null
  • 键值对数据无序

返回类型

方法

描述

Object

get(Object key)

根据key取得value

Object

put(Obejct k,Object v)

向集合中加入元素

void

clear()

清除Map集合

boolean

isEmpty()

判断集合是否为空

boolean

containsKey(Object object)

判断指定的key是否存在

boolean

containsValue(Object value)

判断指定的value是否存在

Set

keySet()

Map中所有的key的集合

Object

remove(Object key)

根据key删除对应的value

Collection

values()

取出全部的value

int

size()

获得集合的长度

3.1 HashMap实现类

HashMap实现了Map接口,拥有Map接口的基本特点。HashMap线程不安全,效率高。HashMap的底层是由哈希表、链表加红黑树构成的。

3.1.1创建HashMap对象

		//默认初始化大小16 负载因子0.75
        Map hashMap1 = new HashMap();
        Map hashMap2 = new HashMap(16);
        Map hashMap3 = new HashMap(16,0.75f);

3.1.2添加操作

		 /*添加操作*/
        //存储按键值对
        hashMap1.put("张三",18);
        hashMap1.put("李四",19);
        hashMap1.put("王五",20);
        //键不能重复 否则覆盖值
        hashMap1.put("王五",21);
        System.out.println(hashMap1);
        //添加多个键值对
        hashMap2.putAll(hashMap1);
        System.out.println(hashMap2);
        /*hashMap1.putIfAbsent():如果指定的key存在,则不放入hashmap1中 如果不存在则放入*/
        hashMap1.putIfAbsent("赵六",20);
        hashMap1.putIfAbsent("赵六",21);
        System.out.println(hashMap1);

3.1.3删除操作

 		/*删除操作*/
        hashMap1.remove("王五");
        System.out.println(hashMap1);
        hashMap2.clear();//清空map容器
        System.out.println(hashMap2);

3.1.4查询操作

		/*查询操作*/
        hashMap1.put("王五",19);
        System.out.println(hashMap1);
        boolean f = hashMap1.containsKey("张三");//是否包含指定的key
        System.out.println(f);
        Object v = hashMap1.get("张三");//根据key获得value
        System.out.println(v);
        Set set = hashMap1.keySet();//获得key集合
        System.out.println(set);
        //遍历 根据key集合获得其值
        for (Object key:set) {
            Object value = hashMap1.get(key);
            System.out.println(key+"====>"+value);
        }

3.1.5修改操作

		hashMap1.replace("李四",17);
        System.out.println(hashMap1);

3.1.6 HashMap的底层原理

JDK1.7 和 JDK1.8他们是有区别得。
JDK1.7使用得数据结构: 数组+链表  而且链表插入模式为头部插入(造成死循环)。
jdk1.8使用得数据结构: 数组+链表+红黑树 而且链表得插入模式为尾部插入。

从构造函数入口:
/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

总结:JDK1.8 HashMap原理
Hashmap得原理,存储元素使用得put(key,value),根据key得hash计算出相应得哈希值,根据相应得算法求出该元素在数组中得位置, 如果求出得哈希值相同,则称为哈希冲突,会根据equals来判断元素是否一致,如果equals不同,则存入单向链表上, 如果哈希碰撞得个数超过8个,则把链表转换为红黑二叉树。

JDK1.7和JDK1.8 HashMap得区别。
   JDK1.7使用得数据结构: 数组+链表  而且链表插入模式为头部插入(造成死循环)。
   jdk1.8使用得数据结构: 数组+链表+红黑树 而且链表得插入模式为尾部插入。

//底层代码如下
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                 //如果key得hash值相同,判断key得equals是否相同,替换原来得元素
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        // 判断链表得长度是否超过8个
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            // 把链表转换为红黑树结构
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

4.1泛型

1. 泛型就是限制我们得数据类型。

2.为什么使用泛型?
我们原来在定义集合时,是如下得定义方式:
    List list=new ArrayList();//该集合没有使用泛型
    list.add("java01");
    list.add("java02");

    String str= (String) list.get(0);//获取元素 需要进行强制类型转换
    System.out.println(str);
获取元素时,不方便对元素进行相应得其他操作。
3.使用泛型
List<类型>  list=new ArrayList<类型>(); 只能在该集合中存储指定得类型。
public static void main(String[] args) {
    List<String> list=new ArrayList<>();//这里就限制了集合中每个元素得类型。
    list.add("java01");
    list.add("hello"); //因为集合中只能添加String类型
    list.add("world"); //因为集合中只能添加String类型

    String s = list.get(0); //在获取元素时 默认就是相应得数据类型 而无需在进行转换

    //<K,V>:K:表示键得泛型  V:表示值得泛型
    HashMap<String,Integer> map=new HashMap<>();
    map.put("name",15);
    map.put("age",25);
    Set<String> keys = map.keySet();
}
4.自定义泛型
public class Test03 {
public static void main(String[] args) {
    //在创建泛型类对象时没有指定相应得泛型类型。则默认为Object类型
    Point p1=new Point();
    p1.setX(15);
    p1.setX("北纬50度");

    //这里得泛型必须都是对象类型
    Point<Integer> p2=new Point<Integer>() ;
    p2.setX(25);
    p2.setY(65);
    Integer x = p2.getX();
    Integer y = p2.getY();
    p2.show();

    Point<String> p3=new Point<>();
}
}


class Point<T>{

 private T x;
 
 private T y;
 
 public void show(){
     System.out.println("x坐标为:"+x+";y坐标为:"+y);
 }

public T getX() {
    return x;
}

public void setX(T x) {
    this.x = x;
}

public T getY() {
    return y;
}
public void setY(T y) {
    this.y = y;
}
}

  1.  需要数据唯一时,使用Set集合
  2. 需要保持规则顺序,此时用TreeSet
  3. 不需要指定顺序,此时用HashSet
  4. 需要保证代码添加数据的次序,此时用LinkedHashSet
  5. 不需要唯一时,使用List集合
  6. 需要频繁增删操作时,使用LinkedList
  7. 不需要频繁增删操作,需要做大量查询操作时,使用ArrayList
  8.  如果以键值对方式存储数据时,使用HashMap

 通过类名记住集合框架类的结构和所属体系

List: ArrayList LinkedList

Set : HashSet TreeSet

后缀名就是该集合所属的体系。

前缀名就是该集合所属的数据结构。

看到array:想到的就是数组,查询速度快。因为有角标是连续的内存地址。

看到link:想到的就是链表,增删动作的速度快,而且要想到 add get remove+first /last的 方法

看到hash:想到的就是哈希表,那么就具有唯一性,

而且要想到元素需要覆盖hashcode方法 和equals方法

看到tree:想到的就是二叉树,接下来想到的就是排序,然后就是两个接口 Comparable接口

实现compareTo(To) Comparator接口 实现compare() 方法
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值