欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础——集合框架

程序员文章站 2022-05-23 16:21:35
...

一、集合

         Java集合类存放于 java.util 包中,是一个用来存放对象的容器。Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。

     1)集合中只能存放对象;

     2)集合存放的是对象的引用,对象本身仍在堆内存中;

     3)集合可以存放不同类型、不同数量的数据类型(Map)。

二、集合框架    Java基础——集合框架

图片来源:http://blog.csdn.net/u010887744/article/details/50575735

高清图地址:https://img-blog.csdn.net/20160124221843905

三、集合详解

  Collection集合框架

  顶层接口:

public interface Iterable<T> {
    /**
     * 返回类型 T元素的迭代器。
     */
    Iterator<T> iterator();

    /**
     * 执行给定的操作的每个元素 Iterable直到所有的元素都已经被处理或行动将抛出一个异常。
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * 在Iterable描述的元素上创建一个spliterator
     * @since 1.8
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

  迭代器接口:

public interface Iterator<E> {
    /**
     * 如果仍有元素可以迭代,则返回 true。
     */
    boolean hasNext();

    /**
     * 返回迭代的下一个元素
     */
    E next();

    /**
     * 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    /**
     * 为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常。
     * @since 1.8
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }

}

  核心接口:

public interface Collection<E> extends Iterable<E> {
         ..........
}

  子接口:

  1)、List<E>:有序,可重复,有索引 

public interface List<E> extends Collection<E> {
            .........
}

   实现类:

        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new LinkedList<>();
        List<Integer> list3 = new Vector<>();

  ArrayList<E>:ArrayList是基于数组实现的List类,它封装了一个动态的增长的、允许再分配的Object[]数组。

          特点:底层数据结构是数组,查询快,增删慢;线程不安全,效率高;

  LinkedList<E>:implements List<E>, Deque<E>。实现List接口,能对它进行队列操作,即可以根据索引来随机访问集合中的    元素。同时它还实现Deque接口,即能将LinkedList当作双端队列

          特点:底层数据结构是链表,查询慢,增删快;线程不安全,效率高;

  Vector<E>:Vector和ArrayList在用法上几乎完全相同,基本被淘汰

          特点:底层数据结构是数组,查询快,增删慢;线程安全,效率低,几乎已经淘汰了这个集合;

  其他:

          Stack:vector提供的字类,用于模拟"栈"这种数据结构(LIFO后进先出)

          CopyOnWriteArrayList:

         CopyOnWriteArrayList是ArrayList的线程安全的变体,其中的所有可变操作(add, set等)都是对底层数组进行一次新的复制来实现的,相比ArrayList的要慢一些,适用于读多写少的场景 ;

          在并发操作容器对象时不会抛出ConcurrentModificationException,并且返回的元素与迭代器创建时的元素是一致的 ;
          容器对象的复制需要一定的开销,如果对象占用内存过大,可能造成频繁的YoungGC和Full GC ;
          CopyOnWriteArrayList不能保证数据实时一致性,只能保证最终一致性

  2)、Set<E>:不可重复,无索引

public interface Set<E> extends Collection<E> {
            .........
}

  实现类:

        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new LinkedHashSet<>();
        Set<Integer> set3 = new TreeSet<>();

  HashSet<E>:HashSet是Set接口的典型实现,HashSet使用HASH算法来存储集合中的元素,因此具有良好的存取和查找性      能。当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该    HashCode值决定该对象在HashSet中的存储位置。

  HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法的返回值相等

  特点:底层数据结构是数组;无序、不可重复;线程不安全;

  LinkedHashSet<E>:

  特点底层采用 链表和哈希表的算法,链表保证元素的添加顺序,哈希表保证元素的唯一性;有序、不可重复;线程不安全;

  TreeSet<E>:TreeSet是SortedSet接口的唯一实现类,可以确保集合元素处于排序状态

  特点:底层使用红黑树算法,擅长于范围查询;有序、不可重复;线程不安全;

  3)、Queue<E>:链表结构,先进先出

public interface Queue<E> extends Collection<E> {
                ...........
}

 Map集合框架

key-value 的键值对,key 不允许重复,value 可以;双列

HashMap<K,V>:线程不安全

ConcurrentHashMap<K,V>:线程安全

四、集合遍历

  遍历ArrayList

import java.util.*;
/**
 * 三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度。
 */
public class Test{
 public static void main(String[] args) {
     List<String> list=new ArrayList<String>();
     list.add("Hello");
     list.add("World");
     list.add("HAHAHAHA");
     //第一种遍历方法使用foreach遍历List
     for (String str : list) {            //也可以改写for(int i=0;i<list.size();i++)这种形式
        System.out.println(str);
     }
 
     //第二种遍历,把链表变为数组相关的内容进行遍历
     String[] strArray=new String[list.size()];
     list.toArray(strArray);
     for(int i=0;i<strArray.length;i++) //这里也可以改写为  foreach(String str:strArray)这种形式
     {
        System.out.println(strArray[i]);
     }
     
    //第三种遍历 使用迭代器进行相关遍历
     
     Iterator<String> ite=list.iterator();
     while(ite.hasNext())//判断下一个元素之后有值
     {
         System.out.println(ite.next());
     }
 }
}

遍历Map

import java.util.*;
 
public class Test{
     public static void main(String[] args) {
      Map<String, String> map = new HashMap<String, String>();
      map.put("1", "value1");
      map.put("2", "value2");
      map.put("3", "value3");
      
      //第一种:普遍使用,二次取值
      System.out.println("通过Map.keySet遍历key和value:");
      for (String key : map.keySet()) {
       System.out.println("key= "+ key + " and value= " + map.get(key));
      }
      
      //第二种
      System.out.println("通过Map.entrySet使用iterator遍历key和value:");
      Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
      while (it.hasNext()) {
       Map.Entry<String, String> entry = it.next();
       System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }
      
      //第三种:推荐,尤其是容量大时
      System.out.println("通过Map.entrySet遍历key和value");
      for (Map.Entry<String, String> entry : map.entrySet()) {
       System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }
    
      //第四种
      System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
      for (String v : map.values()) {
       System.out.println("value= " + v);
      }
     }
}

遍历Set

import java.util.HashSet;
import java.util.Iterator;

public class SetTest {
    public static void main(String[] args) {
        HashSet<String> sets = new HashSet<>();
        sets.add("h");
        sets.add("e");
        sets.add("l");
        sets.add("l");//不可重复
        sets.add("0");

        //方法一:迭代遍历
        for (Iterator<String> iterator = sets.iterator(); iterator.hasNext();){
            System.out.println(iterator.next());
        }
        //输出结果:
        /*
        0
        e
        h
        l
         */
       //可以看出Set集合是不可重复(添加重复操作不会报错)且无序的

        //方法二:foreach循环(没有普通for循环方法)
        for (String value:sets) {
            System.out.println(value);
        }
    }
}

 

相关标签: 集合