Java集合那点事, 满满干货~

说到Java集合,可以说是初学者必踩的坑了。

那么怎么才能学好Java集合呢?个人认为关键是要理清楚思路,从上而下,建立一套完整的思维体系,这样才能更好的去认识事物的本质。

先确立一下学习Java集合的目标:

1.会使用集合存储数据。

2.会遍历集合,把数据取出来。

3.掌握每种集合的特性。

总的集合框架如图所示:

集合框架

 Collection<E>接口

首先从Collectiion 讲起 ,Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些操作方法可以用于操作多有的单列集合(所有子类都可以使用)。

方法如下(重点):                                                                                    

* public boolean add(E e): 把给定的对象添加到当前集合中。                 

* public boolean clear():清空集合中所有的元素。                                 

* public boolean remove(E e):把给定的对象在当前集合中删除。         

* public int size():输出集合中元素个数。                                               

* public bollean contains(E e):判断当前集合是否包含指定对象。        

* public boolean isEmpty():判断当前集合是否为空。

* public Object [ ] toArray:把集合中的元素储存在数组中

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

public class DemoCollection{
    public static void main(String[] args){
        //创建集合对象,使用多态。
        Collection<String> coll = new ArrayList<>();//ArrayList是Collection的实现类
        System.out.println(coll);
        coll.add("寒冰射手");
        coll.add("无双剑姬");
        coll.add("满族之王");
        System.out.println(coll);

        boolean b1= coll.remove("寒冰射手");//添加对象
        System.out.println("b1是否移除:"+b1);

        boolean b2 = coll.contains("无双剑姬");//判断对象是否存在集合当中
        System.out.println("b2是否包含:"+b2);

        int size = coll.size();//返回集合的大小
        System.out.println("size:"+size);

        if(coll.isEmpty()){  //判断集合是否为空
            System.out.println("集合为空");
        }else{
            Object[] arr = coll.toArray();//把集合中的元素存储在数组当中
            for(int i = 0;i<arr.length;i++){
                System.out.println("arr[i]");//输出数组中的元素
            }
        }
        
        //使用迭代器遍历集合
        Iterator<String> it = coll.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.println(str);
        }
        
        //coll.clear();清空集合当中的元素
    }
}

List 接口(java.util.List)

List接口继承自Collection接口,一般将List接口的对象称为List集合。List集合中重要是允许出现重复的元素,所有的元素以线性的方式存储。

List接口的特点:

1.有序的集合,存储元素和储存元素的顺序是一致的。

2.有索引,包含了一些带索引的方法(Collection抽取所有子接口的共性,所以不带索引)。

3.允许存储重复的元素。

List接口的常用方法(带索引 特有):

* public void add(int index,E element):将指定元素,添加在集合中的指定位置上。

* public E get (int index):返回集合中指定位置的元素。

* public E remove(int index):返回移除集合指定位置的元素。

* public E set(int index):返回替换集合中指定位置的元素。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class DemoSet {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();//创建List集合对象,使用多态
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        System.out.println(list);
        
        list.add(2,"f");//指定位置添加元素
        System.out.println(list);
        
        list.remove(3);//移除指定位置元素
        System.out.println(list);

        String str = list.get(1);//获取指定位置元素
        System.out.println(str);

        list.set(0,"p");//替换指定位置元素
        System.out.println(list);

        Iterator<String> it = list.iterator();//使用迭代器顺序取出元素,
        while(it.hasNext()){
            String str1 = it.next();
            System.out.println(str1);
        }


    }
}

ArrayList集合

ArrayList为List接口的实现类,底层储存为数组结构,用于元素的增删改查,属于最常用的集合(不同步)

常用方法:

* public boolea add(E e);

* public E get(int index);

* public E remove(int index);

* public int size();

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

public class DemoSet {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        System.out.println(list);
        
       //注意,for循环遍历,长度用list.size
        for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            System.out.println(str);
        }
        
       //迭代器遍历
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str1 = it.next();
            System.out.println(str1);
        }

    }
}

LinkedList集合

LinkedList也为List接口的实现类,但其与ArrayList集合不同的是其底层数据存储的结构为链表结构(双向),包含大量操作首位元素的方法,查询慢,增删快。

常用方法(特有方法,不能使用多态):

* public void addFirst(E e):将指定元素插入此列表开头。

* public void addLast(E e):将指定元素插入此列表的末尾。

* public E getFirst():返回此列表的第一个元素。

* public E getLast():返回此列表的最后一个元素。

* public E removeFirst():移除并返回此列表第一个元素。

* public E removeLast():移除并返回此列表的最后一个元素。

* public E pop():从此列表所表示的堆栈处弹出一个元素。(等效与removeFirst()方法)

* public void push(E e):将元素推入此列表所表示的堆栈。(等效于add()方法)

* public boolean isEmpty():如果列表不包含元素,则返回true。

import java.util.Iterator;
import java.util.LinkedList;


public class DemoSet {
    public static void main(String[] args) {
        show1();
    }

    public static void show1(){
        LinkedList<String> list = new LinkedList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.push("f");
        System.out.println(list);

        String f1 = list.getFirst();
        System.out.println(f1);

        String l1 = list.getLast();
        System.out.println(l1);

        String s1 = list.removeFirst();//等效pop()方法
        System.out.println(s1);

        String s2 = list.removeLast();
        System.out.println(s2);
        
        //list.clear(); 清空集中的元素,在获取集合中元素时会抛出NoSuchElementException

        //使用迭代器遍历Linked中的元素
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.println(str);
        }


    }
}

 Vector集合

 Vector也继承自List接口,底层也是一个实现可增长的对象数组,也可以通过索引来进行访问,但一般Vector使用较少,所以不在这进行详细讲解。

一般方法(特有):

* public void addElement(E e):添加元素到向量末尾。(等效于add()方法)

* public Enumeration<E> elements():返回该向量枚举。

Set接口

Set接口是Collection接口下第二大分支,也继承Collection接口。

Set接口特点:

1.不允许存储相同的元素

2.没有索引,没有带索引的方法,也不能使用普通的for循环。(一般来说,有索引就可以使用for循环来遍历)

Set方法不在详细描述,基本与Collection接口方法一致。

HashSet

HashSet是Set接口的实现类,由哈希表支持(HashMap实例),它不保证set的迭代顺序,即存储元素和取出元素的顺序有可能不一致。

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

public class DemoSet {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(1);
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
            int a = it.next();
            System.out.println(a);
        }
    }
}

关于Set集合不允许重复元素的原理

Set集合在调用add方法时,add()方法会调用元素的hashCode方法和equals方法判断元素是否重复。

前提:存储的元素必须重写hashCode和equals方法。(如用HashSet存储自定义对象,必须重写equals和hashCode方法)

说一下hashCode()方法 :返回一个int型的哈希值(一串数字)。

import java.util.HashSet;

public class DemoSet {
    public static void main(String[] args) {
      HashSet<String> set = new HashSet<>();
      String s1 = new String("abc");
      String s2 = new String("abc");
      set.add(s1);
      set.add(s2);
      set.add("你好");
      set.add("我好");
      set.add("abc");
        System.out.println(set);
    }
}

set.add(s1): add方法会调用s1的hashCode方法,计算“abc”的哈希值,在集合中找有没有和“abc”哈希值一样的元素,发现没有就会把s1储存在集合当中。

set.add(s2):同上操作,发现有哈希冲突后,就会调用s2的equals方法去比较s2.equals(s1),equals返回true,认定两个元素相同,就不会把s2储存在集合当中。

set.add:("你好"):同s1操作相同。

set.add("我好"):哈希值与“你好”相同,但是equals方法返回false,认定“你好”,“我好”不同,就会把“我好”元素挂在“你好”下面,放入集合。

hashSet集合的 底层 哈希表结构 :数组+链表/红黑树。

数组 哈希值1 哈希值2
链表 元素1 元素3
链表 元素2 元素4

LinkedHashSet集合

特点:继承了HashSet集合,其底层是一个哈希表+链表,多了一条链表(记录元素的存储顺序),保证元素有序。

具体方方不再详述,与HashSet相同。

Collections集合工具类:

对集合进行操作,部分方法如下:

* public static <T> boolean addAll(Collection<T> c,T..elements):往集合中添加多个元素。   

* public static void shuffle(List<?> List):打乱集合中元素的顺序  。

* public static <T> void sort(List<T> list):将集合中元素按默认规则排序元素。(升序)

   *注意:如果是自定义类型,使用sort()需要重写compaerTo()方法.

* public static <T> void sort(List<T>,Comparator<?super T>) :将集合中元素按指定规则排序。

  例如:Collections.addAll(list,"a","b".....)(静态方法调用,直接类名.方法)。

Map<K,V>集合(有点懒,包括其子类就放一块讲完啦)

<key,value>双列集合,通多键值对方式组成。通过建可以找到其值。

Map集合的特点:

1.Map集合是一个双列集合,一个元素包含两个值(key,value)。

2.Map集合中的元素,key和value的数据类型可以相同,也可以不同。

3.Map集合中的元素,键是不允许重复的,但是值是可以重复的。

常用方法:

* public V put(K key,V value):把指定的键与值添加到Map集合当中。(存储键值对时,键相同,值不同,后添加的值会把原来的值覆盖)

* public V remove (Object key):把指定的键所对应的值对元素在Map集合中删除,返回被删除元素的值。

* public V get(Obejec key):获取键所对应的值

* boolean containsKey(Object key):判断集合中是否包含指定的键。

* public Set<K> keySet():获取Map集合中的所有键,并把它放入Set集合。(重要)

* public Set<Map.Entry<K,V>> entrySet():把键值对的对象(Entry)放入Set集合中。(重要)

import java.util.*;

public class DemoSet {
    public static void main(String[] args) {
      Map<String,String> map = new HashMap<>();
      map.put("a","a");
      map.put("b","b");
      map.put("c","c");
      map.put("d","d");
      map.put("a","f");
      System.out.println(map);

      String str1 = map.get("a");
      System.out.println(str1);

      String str2 = map.remove("c");
      System.out.println(str2);
      System.out.println(map);

      boolean flag = map.containsKey("c");
      System.out.println("键C是否存在:"+flag);

      //遍历键值对,注意和之前的集合遍历不太一样
      Set<String> set = map.keySet();
      Iterator<String> it = set.iterator();
      while(it.hasNext()){
        String key = it.next();
        String value = map.get(key);
        System.out.println(key+"="+value);
      }
      System.out.println("------------------------------------");//华丽的分割线 Map.Entry为其Map内置接口
      //使用entrySet遍历
      Set<Map.Entry<String, String>> entry = map.entrySet();
      Iterator<Map.Entry<String, String>> iterator = entry.iterator();
      while(iterator.hasNext()){
        Map.Entry<String, String> next = iterator.next();
        System.out.println(next);
      }
      System.out.println("------------------------------------");//华丽的分割线
      //也可使用增强for循环遍历
      for(Map.Entry<String, String> s1:map.entrySet()){
        System.out.println(s1);
      }

    }
}

*注意:Map.Entry<k,v>:在Map接口中由一个内部接口Entry,当Map集合一创建,就会创建一个Entry对象,用来记录键值对。

可以把Map.Entry<K,V>,理解成一种引用类型,在增强for循环中去遍历使用,用来接收传来的键值对。

HashMap集合

HashMap<k,v>集合为Map<k,v>接口的实现类,其底层为哈希表。为无顺序集合的集合,即存取顺序不一致,线程不安全,不同步,多线程。

Hashmap存储自定义类型键,自定义类型的键就要重写hashcode方法和equals方法,保证键的唯一性。值可以重复。(具体不详述)

LinkedHashMap集合

LinkedHashMap是HashMap的子类。其底层是哈希表+链表(保证迭代顺序),它是一个有序的集合,存取顺序一致。

Hashtable集合

Hashtable为Map接口的实现类,其底层也为哈希表,同步且为单线程集合,不常用。Hashtable 不能存取null值。

如果在Hashtable集合中存放null,则会抛出NullPointerException异常。

但是Hashtable的子类Properties集合依然活跃,Properties是唯一和IO流相结合的集合。

猜你喜欢

转载自www.cnblogs.com/hutree/p/12354880.html
今日推荐