javaSE——集合

一、集合

1、集合和数组的区别

(1)、长度区别

  • 数组固定

  • 长度可变

(2)、内容区别

  • 数组可以是基本数据类型,也可以是引用数据类型

  • 集合只能是引用类型--

(3)、元素内容

  • 数组只能存储同一种类型

  • 集合可以存储不同类型

2、collection集合的方法

Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可以用于操作Set集合,也可用于操作List和Queue集合。Collection接口里定义了如下操作集合元素的方法:

  1. boolean add(Object o):该方法用于向集合中添加一个元素。如果集合对象被添加操作改变了,则返回true

  2. boolean addAll(Collection c):该方法把集合c里的所有元素添加到指定集合里。如果集合对象被添加操作改变了,则返回true。

  3. void clear():清楚集合里所有元素,将集合长度变为0。

  4. boolean contains(Object o):返回集合里是否包含指定元素

  5. boolean containsAll(Collection c):返回集合里是否包含集合c里的所有元素

  6. boolean isEmpty():返回集合是否为空。当集合长度为0时返回true,否则返回flase

  7. Iterator iterator():返回一个Iterator对象,用于遍历集合里的元素

  8. boolean remove(Object o):删除集合中的指定元素o,当集合中包含一个或多个元素o时,该方法只删除第一个符合条件的元素,该方法返回true。

  9. boolean removeAll(Collection c):从集合中删除集合c里包含的所有元素(相当于把调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true

  10. boolean retainAll(Collection c):从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。

  11. int size():该方法返回集合里元素的个数。

  12. Object[] toArray():该方法把集合转换成一个数组,所有集合元素变成对应的数组元素。

创建两个Collection对象,一个是c集合,一个是books集合,其中c集合是ArrayList,而books集合是HashSet,虽然使用的实现类不同,但当把他们当成Collection来使用时,使用add、remove、clear等方法来操作集合元素时没有任何区别。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class CollectionTest{
     public static void main(String[] args) {
         Collection c = new ArrayList();
         //添加元素
         c.add(6);
         //虽然集合里不能放基本类型的值,但java支持自动装箱
         c.add(6);
         System.out.println("c集合里的元素个数为:"+c.size());         //输出2
         //删除指定元素
         c.remove(6);
         System.out.println("c集合里的元素个数为:"+c.size());         //输出1
         //判断是否包含指定字符串
         System.out.println("c集合是否包含\"ABC\"字符串:"+c.contains("ABC"));       //输出true
         c.add("语文课程");
         System.out.println("c集合里的元素:"+c);
         Collection books = new HashSet();
         books.add("英语课程");
         books.add("数学课程");
         System.out.println("c集合是否完全包含books集合?"+c.containsAll(books));        //输出flase
         //用c集合减去books集合里的元素
         c.removeAll(books);
         System.out.println("c集合里的元素:"+c);
         c.clear();
         System.out.println("books集合里的元素"+c);
         //控制books集合里只剩下c集合里也包含的元素
         books.retainAll(c);
         System.out.println("books集合里的元素:"+books);
     }
}

输出:
c集合里的元素个数为:2
c集合里的元素个数为:1
c集合是否包含"ABC"字符串:false
c集合里的元素:[6, 语文课程]
c集合是否完全包含books集合?false
c集合里的元素:[6, 语文课程]
books集合里的元素[]
books集合里的元素:[]

3、常用集合的分类

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

List 接口:元素按进入先后有序保存,可重复

LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全

ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全

Vector 接口实现类 数组, 同步, 线程安全

Stack 是Vector类的实现类

Set 接口: 仅接收一次,不可重复,并做内部排序

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

LinkedHashSet 链表维护元素的插入次序

TreeSet 底层实现为二叉树,元素排好序

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

Hashtable 接口实现类, 同步, 线程安全

HashMap 接口实现类 ,没有同步, 线程不安全

LinkedHashMap 双向链表和哈希表实现

WeakHashMap

TreeMap 红黑树对所有的key进行排序

IdentifyHashMap

4、遍历集合

(1)、使用Lambda表达式遍历集合

Iterator接口新增了一个forEach(Consumer action)默认方法,该方法所需要参数的类型是一个函数式接口。而Iterator接口是Collection接口的父接口,因此Collection集合也可以直接调用该方法。

import java.util.Collection;
import java.util.HashSet;
public class CollectionEach{
     public static void main(String[] args) {
         //创建一个集合
         Collection books = new HashSet();
         books.add("字符串1");
         books.add("字符串2");
         books.add("字符串3");
         //调用forEach()方法遍历集合
         books.forEach(obj->System.out.println("迭代集合元素:"+obj));
     }
}

输出:
迭代集合元素:字符串2
迭代集合元素:字符串1
迭代集合元素:字符串3

(2)、使用Iterator遍历集合

Iterator接口定义了如下四个方法:

  1. boolean hasNext():如果被迭代的集合元素还没有被遍历完,则返回true。

  2. Object next():返回集合里的下一个元素。

  3. void remove():删除集合里上一次next方法返回的元素

  4. void forEachRemaining(Consumer action):java 8为Iterator新增的默认方法,该方法可使用Lambda表达式来遍历集合元素

Iterator必须依赖于Collection对象,一个Iterator对象必然有一个与之关联的Collection对象。Iterator提供了两个方法来迭代访问Collection集合里的元素,并可以通过remove()方法删除集合中上一次next()方法返回的集合元素。

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorTest{
     public static void main(String[] args) {
        //创建集合
        Collection books = new HashSet();
        books.add("字符串1");
        books.add("字符串2");
        books.add("字符串3");
          //获取books集合对应的迭代器
         Iterator it = books.iterator();
         while(it.hasNext()) {
              //it.next()方法返回的数据类型是Object类型,因此需要强制类型转换
              String book = (String)it.next();
              System.out.println(book);
              if(book.equals("字符串")) {
                  //从集合中删除上一次next()方法返回的元素
                  it.remove();
              }
              //对book变量赋值,不会改变集合元素本身
              book = "测试字符串";
         }
         System.out.println(books);
     }
}

输出:
字符串2
字符串1
字符串3
[字符串2, 字符串1, 字符串3]

(3)、使用Lambda表达式遍历Iterator集合

java 8为Iterator新增了一个forEachRemaining(Consumer action)方法,该方法所需要的Consumer参数同样也是函数式接口。

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorEach{
     public static void main(String[] args) {
         //创建一个集合
         Collection books = new HashSet();
         books.add("字符串1");
         books.add("字符串2");
         books.add("字符串3");
         //获取books集合对应的迭代器
         Iterator it = books.iterator();
         //使用Lambda表达式(目标类型是Comsumer)来遍历集合元素
         it.forEachRemaining(obj->System.out.println("迭代集合元素:"+obj));
     }
}

输出:
迭代集合元素:字符串2
迭代集合元素:字符串1
迭代集合元素:字符串3

(4)、使用foreach循环遍历元素

与使用Iterator接口迭代访问集合元素类似的是,foreach循环中的迭代变量也不是集合元素本身,系统只是以此把集合元素的值赋给迭代变量,因此在foreach循环中修改迭代变量的值也没有任何意思。同样,使用foreach循环迭代访问集合元素是,该集合也不能改变。

import java.util.Collection;
import java.util.HashSet;
public class FroeachTest{
     public static void main(String[] args) {
         //创建一个集合
         Collection books = new HashSet();
         books.add("字符串1");
         books.add("字符串2");
         books.add("字符串3");
         for (Object obj:books) {
             //此处的book变量也不是集合元素本身
             String book = (String)obj;
             System.out.println(book);
         }
         System.out.println(books);   
     }
}

输出:
字符串2
字符串1
字符串3
[字符串2, 字符串1, 字符串3]

二、list和set集合

1、list和set集合区别

(1)、有序性

  • list保证按插入的顺序排序

  • set存储和取出顺序不一致

(2)、唯一性

  • list可以重复

  • set元素唯一

(3)、获取元素

  • list可以通过索引直接操作元素

  • set不能根据索引获取元素

2、set集合

Set接口继承了Collcetion接口,包含Collcetion中的所有方法。

(1)、set接口的实现类

  • HashSet类实现了Set接口,不保证Set的迭代顺序,特别是它不保证该顺序恒久不变,此类允许使用null元素

  • TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此,TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序

TreeSet类增加的方法

方法

功能描述

first()

返回此Set中当前第一个(最低)元素

last()

返回此Set中当前最后一个(最高)元素

comparator()

返回对此Set中的元素进行排序的比较器;如果此Set使用自然顺粗,则返回null

headSet(E toElement)

返回一个新的Set集合,新集合是toElement(不包含)之前的所有对象

subSet(E fromElement,E fromElement)

返回一个新的Set集合,是fromElement(包含)对象与fromElement(不包含)对象之间的所有对象

tailSet(E fromElement)

返回一个新的Set集合,新集合包含对象fromElement(包含)之后的所有对象

(2)、Set特点

元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)

检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

(3)、HashSet类

HashSet是Set接口的典型表现,大多数时候使用set集合就是使用这个实现类。

HashSet按Hash算法来存储集合中的元素,因此具有很好的存储和查找性能。底层数据结构是哈希表。(无序,唯一) 如何来保证元素唯一性?

依赖两个方法:hashCode()和equals()

HashSet特点如下:

  1. 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化

  2. HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程通知修改了HashSet集合时,则必须通过代码来保证其同步

  3. 集合元素值可以实null

如下程序提供了三各类A、B和C,他们分别重写了equals()、hasCode()两个方法的一个或全部。注意:当把一个对象放入HashSet中时,如果有重写该对象对应类的equals()方法,则也应该重写hashCode()方法。规则是:如果有两个对象通过equals()方法比较返回true,这两个对象的hashCode()值也应该相同。

import java.util.HashSet;
//类A的equals()方法总是返回true,但没有重写其hashCode()方法
class A{
     public boolean equals(Object obj) {
         return true;
     }
}
//类B的hashCode()方法总是返回1,但没有重写其equals()方法
class B{
     public int hashCode() {
         return 1;
     }
}
//类C的hashCode()方法总是返回2,且重写其equals()方法总是返回true
class C{
     public int hashCode() {
         return 2;
     }
     public boolean equals(Object obj) {
         return true;
     }
}
public class HashSetTest{
     public static void main(String[] args) {
         HashSet books = new HashSet();
         //分别向books集合中添加两个A对象、两个B对象、两个C对象
        books.add(new A());
        books.add(new A());
        books.add(new B());
        books.add(new B());
        books.add(new C());
        books.add(new C());
        System.out.println(books);
     }
}

输出:
[Text.B@1, Text.B@1, Text.C@2, Text.A@27973e9b,  Text.A@5b6f7412]

(4)、LinkedHashSet

底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。

底层数据结构是链表和哈希表。(FIFO插入有序,唯一)

1.由链表保证元素有序

2.由哈希表保证元素唯一

(5)、TreeSet

底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法。

底层数据结构是红黑树。(唯一,有序)

1. 如何保证元素排序的呢?

自然排序

比较器排序

2.如何保证元素唯一性的呢?

根据比较的返回值是否是0来决定

3、List集合

list接口继承了Collcetion接口,包含Collcetion中的所有方法。

方法

功能描述

void add(int index,Object element)

将元素elemet插入到List集合的index处

boolean addAll(int index,Collection c)

将集合c所包含的所有元素都插入到List集合的index处

Object get(int index)

返回集合index索引处的元素

int indexOf(Object o)

返回兑现那个o在List集合中第一次出现的位置索引

int lastIndexOf(Object o)

返回对象o在list集合中最后一次出现的位置索引

Object remove(int index)

返回并删除index索引处的元素

Object set(int index,Object element)

将index索引处的元素替换成element对象,返回被替换的旧元素

List subList(int forIndex,int toIndex)

返回从索引fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合

void replaceAll(UnaryOperator operator)

根据operator指定的计算机规则重新设置List集合的所有元素

void sort(Comparator c)

根据Comparator参数对List集合的元素排序

此外,list还定义了两种方法

  • get(int int index):获得指定索引位置的元素

  • set(int inedx,Object obj):缉拿该集合中指定索引位置的对象修改为指定的对象

(1)、List特点

元素有放入顺序,元素可重复

和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

(2)、List接口的实现类

a、ArrayList

实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问;缺点是向指定的索引位置插入对象或删除对象的速度较慢

优点: 底层数据结构是数组,查询快,增删慢。

缺点: 线程不安全,效率高

b、LinkedList

采用链表结构保存对象。优点是便于像集合中插入和删除对象;但对于随机访问集合中的对象,使用LinkedList类实现List集合的效率较低

优点: 底层数据结构是链表,查询慢,增删快。

缺点: 线程不安全,效率高

c、Vector

底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

优点: 底层数据结构是数组,查询快,增删慢。

缺点: 线程安全,效率低

通过ArrayList、LinkedList类实例化List集合

    List<E>List = new ArrayList<>();

    List<E>List2 = new LinkedList<>();

创建集合对象,随机获取集合中的某个元素,然后移除数组中索引位置为”2“的元素,最后遍历数组

    import java.util.*;
    public class Demo {
        public static void main(String[] args) {
            List<String>list = new ArrayList<>(); //创建集合对象
            list.add("a"); //向集合添加数据据
            list.add("b");
            list.add("c");
            int i = (int)(Math.random()*list.size()); //获取0~~2之间的随机数;集合的索引也是从0开始
            System.out.println("随机获取数组中的元素:"+             list.get(i));
            list.remove(2); //将指定索引位置的元素从集合中移除
            System.out.println("将索引是‘2'的元素从数组移除后,数组中的元素是:");
            for(int j = 0 ; j < list.size() ; j++){ //循环遍历集合
                System.out.println(list.get(j));
            }
        }
    }

三、Map集合

1、Map集合

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。

Map 没有继承 Collection 接口, Map 提供 key 到 value 的映射,你可以通过“键”查找“值”。一个 Map 中不能包含相同的 key ,每个 key 只能映射一个 value 。 Map 接口提供 3 种集合的视图, Map 的内容可以被当作一组 key 集合,一组 value 集合,或者一组 key-value 映射。

2、Map接口常用方法

3、Map接口的实现

  • HashMap类是基于哈希表的Map接口的实现,此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

  • TreeMap类不仅实现了Map接口,还实现了java.util.SortedMap接口,因此集合中的映射关系具有一定的顺序

3、TreeSet, LinkedHashSet and HashSet 的区别

(1)介绍

TreeSet, LinkedHashSet and HashSet 在java中都是实现Set的数据结构

  • TreeSet的主要功能用于排序

  • LinkedHashSet的主要功能用于保证FIFO即有序的集合(先进先出)

  • HashSet只是通用的存储数据的集合

(2)、相同点

  • Duplicates elements: 因为三者都实现Set interface,所以三者都不包含duplicate elements

  • Thread safety: 三者都不是线程安全的,如果要使用线程安全可以Collections.synchronizedSet()

(3)、不同点

  • Performance and Speed: HashSet插入数据最快,其次LinkHashSet,最慢的是TreeSet因为内部实现排序

  • Ordering: HashSet不保证有序,LinkHashSet保证FIFO即按插入顺序排序,TreeSet安装内部实现排序,也可以自定义排序规则

  • null:HashSet和LinkHashSet允许存在null数据,但是TreeSet中插入null数据时会报NullPointerException

注意:

  • Hashtable是线程安全的,HashMap不是线程安全的。

  • HashMap效率较高,Hashtable效率较低。 如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。

  • Hashtable不允许null值,HashMap允许null值(key和value都允许)

  • 父类不同:Hashtable的父类是Dictionary,HashMap的父类是AbstractMap

四、Queue集合

Queue接口与List、Set同一级别,都是继承了Collection接口。

Queue用于模拟队列这种数据结构,队列的头部保存在队列中存放时间最长的元素,队列的尾部保存在队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。Queue中定义了如下几个方法:

  1. void add(Object e)

  2. Object element()

  3. boolean offer(Object e)

  4. Object peek()

  5. Object poll()

  6. Object remove()

五、PriorityQueue实现类

PriorityQueue保存队列元素的顺序并不是按加入时的顺序,而是按照队列怨怒的大小进行重新排序。因此调用poll()或者peek()方法取出队列中的元素时,并不是取出最先进入队列的元素,而是取出队列中最小的元素。

PriorityQueue不允许插入null元素,它还需要对队列元素进行排序,PriorityQueue的元素有两种排序方式:

  1. 自然排序

  2. 定制排序

代码:

import java.util.PriorityQueue;
public class PriorityQueueTest{
     public static void main(String[] args) {
         PriorityQueue pq = new PriorityQueue();
         //依次向pq中加入四个元素
         pq.offer(6);
         pq.offer(-3);
         pq.offer(20);
         pq.offer(18);
         //输出pq队列,并不是按元素的加入顺序排列
         System.out.println(pq);
         //访问队列的第一个元素,其实就是队列中最小的元素:-3
         System.out.println(pq.poll());
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DF10F-0001A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值