Java 总结第一弹

Java 集合

1.Collection的简单介绍

1.1 分类

Collection 接口:接口的接口 – 对象的集合(单列集合)

  • List :有序可重复集合接口,包含 LinkedListArrayListVector

    • LinkedList :接口实现类, 以双向链表的形式对数据进行操作

      • 底层为双向链表,线程不安全,效率高
    • ArrayList :接口实现类, 以数组的形式对数据进行操作

      • JDK 1.7JDK 1.8 的区别:

        • JDK 1.7:ArrayList 像饿汉式,直接创建一个初始容量为10的数组
        • JDK 1.8:ArrayList 像懒汉式,未指定容量时,默认初始化容量是 0,当添加第一个元素时,初始化容量为 10
      • 当超出数组的长度时会以 1.5 倍方式扩容

      • 底层为数组,线程不安全,效率高

    • Vector :接口实现类,同样以数组的形式对数据进行操作

      • 未指定容量时,默认初始化容量是 0,当添加第一个元素时,初始化容量为 10

      • 当超出数组的长度时会以 2倍方式扩容

      • 所有的方法都是线程同步,都加了 synchronized 关键字

      • Stack栈是 Vector 类的实现类,其底层也是数组实现的,查询快,增删慢,线程安全,效率底

      ArrayList 与 LinkedList 的比较
         1.ArrayList 基于数组, LinkedList 基于链表
         2.ArrayList 根据索引查询快, 根据内容查询速度几乎相当
         3.ArrayList 尾部添加元素比 LinkedList 快一点(几乎可以忽略), 越靠近头部的位置添加元素, 速度越慢 - copy 的元素越多, 	 			 就越会影响效率, LinkedList 头尾添加元素都比较快, 快将近 1 倍
         4.中间位置添加元素 ArrayList 明显比 LinkedList 快, 将近 4 倍
      
  • Set :无序、不可重复(唯一性)集合接口,包含 TreeSetHashSet

  • 唯一性的实现:

    1.存储元素时首先会使用hash()算法函数生成一个int类型hashCode散列值,然后与所存储的元素的hashCode值比较,如果hashCode不相等,肯定是不同的对象
    2.hashCode值相同,再比较equals方法
    3.equals相同,对象相同。(则无需储存)
    
    • TreeSet :**(SortedSet接口的实现类)**底层实现为红黑树红黑树保证了元素有序

      • 构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,默认加载因子是 0.75

      • 构造一个新的空 set,其底层 HashMap 实例的初始容量指定,加载因子未指定时,加载因子默认是 0.75

      • 构造一个新的空 set,其底层 HashMap 实例的初始容量与加载因子均指定

      • 如不了解红黑树,请先了解数据结构中的二叉树二叉排序树二叉平衡树相关知识

      • 其排序方式分为两类:

        • 自然排序(无参构造),实现 Comparable 接口,重写该接口中的 compareTo(T t) 方法

          该接口位于包 java.lang

          // Comparable源码
          public interface Comparable<T> {
              int compareTo(T t);
          }
          
        • 比较器排序(有参构造),实现 Comparator 接口,重写该接口中的 compare(T o1, T o2) 方法

          该接口位于包 java.util

          // Comparator源码
          public interface Comparator<T> {
              int compare(T o1, T o2);
              boolean equals(Object obj);
          }
          
      • Comparable 与 Comparator 的区别与使用

    • HashSet :使用hash表(数组)存储元素

      • LinkedHashSet :链表维护元素的插入次序
1.2 Collection 的常用方法
// 把给定的对象添加到当前集合中    
public boolean add(E element)
        
// 把指定的集合中的所有元素添加到当前集合中
public boolean addAll(Collection<? extends E> c)

// 清空集合中所有的元素
public void clear()
 
// 判断当前集合中是否包含给定的对象
public boolean contains(E element)
 
// 判断当前集合中是否包含指定集合中的所有元素
public boolean containsAll(Collection<?> c)
        
// 将指定的对象与此集合中的元素进行比较, 相同时返回 True
public boolean equals(E element)

// 返回此集合的哈希值
public int hashCode()

// 判断当前集合是否为空
public boolean isEmpty()

// 把给定的对象在当前集合中删除
public boolean remove(E element)
 
// 把给定的集合中的所有元素在当前集合中删除
public boolean removeAll(Collection<?> c)

// 返回集合中元素的个数
public int size()

// 把集合中的元素,存储到数组中
public Object[] toArray()

// 把集合中的元素,存储到指定类型的数组中
public <T> T[] toArray(T[] a)
  • 这些方法适用于所有能实现此接口的实现类
// 实例
import java.util.ArrayList;
import java.util.Collection;

public class Test01 {
    public static void main(String[] args) {
        // 创建集合对象,使用多态形式
        Collection<String> c1 = new ArrayList<String>();
        Collection<String> c2 = new ArrayList<String>();
        
        // boolean  add(String s)
        c1.add("Hello");
        c1.add("world");
        c1.add("java");
        c1.add("python");
        System.out.println(c1);
        
        c2.add("C语言");
        c2.add("C++语言");
        c2.add("go语言");
        System.out.println(c2);
        
        // boolean addAll(Collection<? extends E> c)
        c1.addAll(c2);
        System.out.println(c1);
        

        // boolean contains(E e) 判断元素e是否在集合中存在
        System.out.println("判断java是否在集合c1中: " + c1.contains("java"));
        
        // boolean containsAll(Collection<?> c) 判断当前集合c1中是否包含指定集合c2中的所有元素
        System.out.println("判断集合c2是否在集合c1中: " + c1.containsAll(c2));
        
        // boolean equals(E e) : 将指定的对象与此集合中的元素进行比较, 相同时返回 True
        // get() 方法为 ArrayList 特有方法, 通过下标来获取对应的对象
        System.out.println("判断集合c1是存在元素python: " + c1.get(3).equals("python"));
        
        // int hashCode() 返回此集合的哈希值
		System.out.println("c1集合的哈希值为: " + c1.hashCode());
     
        // boolean remove(E e) 删除在集合中的元素e
        System.out.println("删除 C++语言: " + c1.remove("C++语言"));
        System.out.println("操作之后集合中元素: " + c1);
        
        // boolean removeAll(Collection<?> c) 把给定的集合中的所有元素在当前集合中删除
        System.out.println("删除集合c1中的给定的c2集合中的所有元素: " + c1.removeAll(c2));
        System.out.println("操作之后集合中元素: " + c1);
        
        // size() 集合中有几个元素, 集合的大小
        System.out.println("集合中有" + c1.size() + "个元素");

        // Object[] toArray()转换成一个Object数组
        Object[] objects = c1.toArray();
        // 遍历数组
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
        
        // <T> T[] toArray(T[] a) 转换成一个指定类型的数组
        String[] str = c1.toArray(new String[0]);
        // 遍历数组
        for (String each:str) {
            System.out.println(each);
        }
        
        // void  clear() 清空集合c2
        c2.clear();
        System.out.println("集合c2中内容为: " + c2);
        
        // boolean  isEmpty()  判断集合是否为空
        System.out.println(c2.isEmpty());     
    }
}
  • 注意:因为 Set 集合是无序的,所以无法通过索引查找对应的元素

  • List 特有的方法:

    • ArrayListLinkedList 共有的方法:

      // 把指定的元素添加到当前集合中指定位置
      public void add(int index, E element)
      
      // 把指定的集合中的所有元素添加到当前集合中指定位置
      public boolean addAll(int index, Collection<? extends E> c)
          
      // 返回指定元素的第一次出现的索引, 如果不存在就返回 -1
      public int indexOf(E element)
       
      // 返回指定元素的最后一次出现的索引
      public int lastIndexOf(E element)
          
      // 删除该集合中指定位置的元素, 返回删除的元素
      public E remove(int index)
          
      // 用指定的元素替换此集合中指定位置的元素, 并将指定位置的元素返回
      public E set(int index, E element)
          
      // 将指定索引位置的元素返回
      public E get(int index)
      
    • ArrayList 特有的方法

      // 从这个集合中删除所有索引在 (包含)fromIndex 和 toIndex(不包含) 之间的元素
      protected void removeRange(int fromIndex, int toIndex)
      
      // 使用提供的 Comparator 对此集合进行排序以比较元素(注意要重写其compare方法)
      public void sort(Comparator<? super E> c)
            
      // 返回该集合中从 fromIndex 到 toIndex 之间的所有元素构成的一个子集合
      public List<E> subList(int fromIndex, int toIndex)
      
      // 修改这个 ArrayList实例的容量是列表的当前大小
      public void trimToSize()
      
    • LinkedList 特有的方法

    • 注意:

      • LinkedList 实现 DequeQueue 接口,即能将 LinkedList 当作双端队列使用
      // 把指定的元素插入到当前集合开头
      public void addFirst(E e)
          
      // 把指定的元素追加到当前集合末尾
      public void addLast(E e) 
          
      // 返回此集合中的第一个元素
      public E getFirst() 
          
      // 返回此集合中的最后一个元素
      public E getLast() 
      
      // 从此集合表示的堆栈中弹出一个元素 --> 相当于removeFirst() 
      public E pop()
          
      // 将指定元素推送到由此集合表示的堆栈上 --> 相当于addFirst(E e)
      public void push(E e)
          
      // 从此集合中删除并返回第一个元素
      public E removeFirst()
          
      // 从此集合中删除并返回第一个元素
      public E removeLast()
          
      // 以上为比较常见的方法
      ---------------------------------------------分割线---------------------------------------------------
      // 以下为较少运用的方法
          
      // 检索但不删除此集合的头(第一个元素), 并将其返回
      public E element() 
      public E peek()
          
      // 检索但不删除此集合的第一个元素,如果此集合为空,则返回 null 
      public E peekFirst()
          
      // 检索但不删除此集合的最后一个元素,如果此集合为空,则返回 null 
      public E peekLast()
          
      // 检索并删除此集合的头(第一个元素)
      public E poll()
          
      // 检索并删除此集合的第一个元素,如果此集合为空,则返回 null 
      public E pollFirst()
          
      // 检索并删除此集合的最后一个元素,如果此集合为空,则返回 null 
      public E pollLast()
          
      // 将指定的元素添加为此集合的末尾
      public boolean offer(E e)
          
      // 在此集合的前面插入指定的元素
      public boolean offerFirst(E e)
          
      // 在该集合的末尾插入指定的元素
      public boolean offerLast(E e)
          
      // 删除此集合中第一个出现的指定元素
      public boolean removeFirstOccurrence()
            
      // 删除此集合中最后一个出现的指定元素
      public boolean removeLastOccurrence()
      
  • Set 继承自 Collection ,拥有其父类的所有方法

    • TreeSet 特有的方法

      // 返回此集合中大于或等于给定元素的最小元素, 如果没有此元素, 则返回 null 
      public E ceiling(E e)
      
      // 返回对此 set 中的元素进行排序的比较器; 如果此 set 使用其元素的自然顺序, 则返回 null
      public Comparator<? super E> comparator() 
                 
      // 返回在此 set 元素上按降序进行迭代的迭代器
      public Iterator<E> descendingIterator() 
                 
      // 返回此 set 中所包含元素的逆序视图
      public NavigableSet<E> descendingSet() 
                
      // 返回此 set 中当前第一个(最低)元素
      public E first()
      
      // 返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素, 则返回 null
      public E floor(E e) 
                 
      // 返回此 set 的部分视图,其元素严格小于 toElement
      public SortedSet<E> headSet(E toElement) 
                
      // 返回此 set 的部分视图, 其元素小于(或等于, 如果 inclusive 为 true)toElement
      public NavigableSet<E> headSet(E toElement, boolean inclusive) 
                
      // 返回此 set 中严格大于给定元素的最小元素; 如果不存在这样的元素, 则返回 null
      public E higher(E e) 
                
      // 返回在此 set 中的元素上按升序进行迭代的迭代器
      public Iterator<E> iterator() 
                 
      // 返回此 set 中当前最后一个(最高)元素
      public E last() 
               
      // 返回此 set 中严格小于给定元素的最大元素; 如果不存在这样的元素, 则返回 null
      public E lower(E e) 
                 
      // 获取并移除第一个(最低)元素; 如果此 set 为空, 则返回 null
      public E pollFirst() 
                
      // 获取并移除最后一个(最高)元素; 如果此 set 为空, 则返回 null
      public E pollLast() 
               
      // 返回此 set 的部分视图, 其元素范围从 fromElement 到 toElement
      public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 
                
      // 返回此 set 的部分视图, 其元素从 fromElement(包括) 到 toElement(不包括)
      public SortedSet<E> subSet(E fromElement, E toElement) 
                 
      // 返回此 set 的部分视图, 其元素大于等于 fromElement
      public SortedSet<E> tailSet(E fromElement) 
                 
      // 返回此 set 的部分视图, 其元素大于(或等于, 如果 inclusive 为 true) fromElement
      public NavigableSet<E> tailSet(E fromElement, boolean inclusive) 
                
      
      /**
       * 注意: 
       *	1.new TreeSet<>(); 无参构造生成对象时, 会进行自然排序
       *	2.new TreeSet<T>(new Comparator<T>() {
       *		 // 自定义比较器,保证顺序
       *		 @Override
       *        public int compare(T t1, T t2) {
       *       	int num = t1.getXXX() - t2.getXXX();
       *          num = (num == 0 ? (t1.hashCode() - t2.hashCode()):num);
       *          return num;
       *       }
       *	});  有参构造时需要自定义比较器
       *
       *
       */
      
    • HashSet 没有特有的方法

      List 基本使用一致,只是输出顺序并不是存入数据时的顺序

    • LinkedHashSet

1.3 Collection 集合的使用

在这里插入图片描述

2.Map 详解
2.1 分类

Map 接口: 键值对的集合 (双列集合)

Hashtable:
	底层是哈希表数据结构, 线程是同步的, 不可以存入null键, null值; 效率较低, 被 HashMap 替代
HashMap:
	底层是哈希表数据结构, 线程是不同步的, 可以存入null键, null值
	要保证键的唯一性, 需要覆盖hashCode方法和equals方法
LinkedHashMap:
	HashMap的子类基于哈希表又融入了链表; 可以为Map集合进行增删提高效率。
TreeMap:
    TreeMap底层是二叉树数据结构, 可以对集合中的键进行排序
    键的排序实现: 
    	方式一: 元素自身具备比较性
            和TreeSet一样原理, 需要让存储在键位置的对象实现Comparable接口, 重写compareTo方法, 也就是让元素自身具备比较性, 			这种方式叫做元素的自然排序也叫做默认排序
        方式二: 容器具备比较性
            当元素自身不具备比较性, 或者自身具备的比较性不是所需要的时候, 此时可以让容器自身具备 --> 定义一个类实现					Comparator接口, 重写compare方法, 并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法
    注意: 当Comparable比较方式和Comparator比较方式同时存在时, 以Comparator的比较方式为主;在重写compareTo或者compare方法	   时,必须要明确比较的主要条件相等时要比较次要条件
2.2 常用方法
public class MethodsInfo {
    
    // 删除所有的映射
    public void clear() 
        
    // 判断该Map集合是否包含指定的键
    public boolean containsKey(Object key) 
    
    // 判断该Map集合是否包含指定键的值
    public boolean containsValue(Object value) 
        
    // 判断该Map集合中是否存在与指定对象相等的映射
    public boolean equals(Object o) 
    
    //  判断该Map集合是否为空
    public boolean isEmpty() 
        
    // (如果此映射包含该键的映射)返回到指定键所映射的值
    public V get(Object key) 

    // 返回该Map集合的哈希码值
    public int hashCode()
        
    // 返回此Map集合中键值映射的数量
    public int size() 
   
    // 返回一个包含了该Map集合所有键值对的Set集合
    public Set<Map.Entry<K,V>> entrySet() 
        
    // 返回一个包含该Map集合所有的键的Set集合
    public Set<K> keySet()
        
    // 返回此Map集合中包含所有键的值的Collection集合
    public Collection<V> values() 
    
    // 将指定的值与该映射中的指定键添加到该Map集合中去
    public V put(K key, V value) 
    
    // 将指定的一个Map集合的所有映射复制到此Map集合中去
    public void putAll(Map<? extends K,? extends V> m) 
    
    // 从该Map集合中删除一个指定键的映射
    public V remove(Object key) 
}
    
2.3 常用子类
  • HashMap

    • 底层实现

      JDK 1.8 之前 数组 + 链表 – 添加元素-头插法

      JDK 1.8之后 数组 + 链表|红黑树 – 添加元素-尾插法

      1.为何要使用红黑树?
      	红黑树用来避免 DoS 攻击,防止链表超长时性能下降,树化应当是偶然情况,是保底策略
      2.为何一开始不使用红黑树?
      	hash 表的查找,更新的时间复杂度是 O(1),而红黑树的查找,更新的时间复杂度是 O(lgn/lg2)
      	TreeNode 占用空间也比普通 Node 的大,如非必要,尽量还是使用链表
      3.红黑树的阈值为何为 8
      	hash 值如果足够随机, 则在 hash 表内按泊松分布
      	在负载因子 0.75 的情况下, 长度超过 8 的链表出现概率是 0.00000006, 树化阈值选择 8 就是为了让树化几率足够小
      4.什么时候会树化?
      	链表长度大于树化阈值8并且数组容量大于64
      5.什么时候会退化为链表
      	a.在扩容时如果拆分树时, 树元素个数 <= 6 则会退化链表
          b.remove 树节点时, 若 root、root.left、root.right、root.left.left 有一个为 null,也会退化为链表
          c.检测为退化前的链表 - 移除以上任意一个节点后, 还不会退化, 再一次移除任意一个节点, 就会退化
      6.索引如何计算
          a.先计算对象的 hashCode() , 在调用 hash() 方法二次哈希
          b.最后与数组容量进行取余运算 % capacity 或者与数组容量减一进行与运算 & (capacity - 1) 获得索引
      7.hashCode 已经存在, 为何还需要 hash() 方法
          二次哈希是为了综合高位数据, 让哈希分布更为均匀
      8.数组容量为何为 2 的 n 次幂
          a.计算索引时效率更高
          b.链表元素扩容时:hash & oldCap == 0 的元素留在原来的位置, 否则新位置 = 旧位置 + oldCap
      
    • 初始化容量大小为 16, 负载因子为 0.75

    • 当超过 初始化大小*负载因子时,就会触发扩容机制 - 扩容为原来的2倍

  • TreeMap

    TreeMap 详解

关于 Set 集合,因为个人使用不多,所有有些地方总结不到位,还请各位小伙伴指正,谢谢您的浏览阅读

有任何错误请指正,谢谢您的阅读,希望对您有所帮助。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值