Java SE 之 Collection集合

     Collection集合

一.Java集合API

  

    Java Collection Framework API

 

    —— 集合,也叫容器(集合的功能相当于容器),Java的集合(容器)是用来“装对象”的。

二.Set集合类(接口)

   —— Set集合几乎等同于 Collection 集合,二者行为完全相似。

1.遍历Set集合

  ① 用迭代器(Iterator<E>)

  ② 用foreach循环

遍历Set集合及部分Collection/Set集合常用方法示例代码:

import java.util.*;

public class CollectionTest 

{

public static void main(String[] args) 

{

//加泛型限制的集合,只能装入<>指定内指定类型的对象

//Collection<String> c1 = new HashSet<String>(); 

//这里不能用new Collection来创建对象,应为Collection集合(接口),而使用

//new HashSet创建对象,HashSet类实现了Collection集合(接口).

Collection<String> c1 = new HashSet<>(); //棱形语法( Since JDK1.7)

//调用add()方法,装入对象

c1.add("刘亦菲");

c1.add("Crystal");

c1.add("Destiny");

    //调用contains()方法,判断是否包含所指定的对象

System.out.println(c1.contains("liuyifei"));

System.out.println(c1.contains("Crystal"));

// foreach遍历集合c1

for(String ele : c1)

{

System.out.println(ele);

}

//Iterator迭代器遍历c1

//(注意:这里因为c2的定义在迭代器之后,所以不能遍历c2

        Iterator<String> it = c1.iterator();   

    //调用IteratorhasNext()next()方法

while(it.hasNext())

{

System.out.println(it.next());

}

       

Collection <String> c2 = new HashSet<>();

c2.add("刘亦菲");

c2.add("crystal");

c2.add("destiny");

//调用remove()方法,相当于做集合 c2-c1

c2.removeAll(c1);

 

//调用isEmpty()方法,判断集合 c2-c1 是否为空

System.out.println(c2.isEmpty());

//输出集合 c2-c1

System.out.println(c2);

//调用addAll()方法,相当于做集合 c2+c1

        c2.addAll(c1);

//输出集合c2+c1

System.out.println(c2);

//调用retainAll()方法,相当于做集合 c2 ∩ c1

        c2.retainAll(c1);

//输出集合c2 ∩ c1

System.out.println(c2);

}

}

2.HashSet类:是Set集合类的实现类

 

① HashSet的存储机制

底层是用一个数组存储元素 ————  这个数组的长度永远是2n次方。

HashSet的构造器HashSet(int initialCapacity, float loadFactor)说明:

—— initialCapacity :控制底层数组长度,默认是16 ,如果传入的数组长度不是2n次方,HashSet会自动将其扩展到2n次方。

—— loadFactor    :当HashSet “感觉到底层数组快满”时,将再次创建一个长度为原数组长度2倍的数组,并将原数组的元素复制到新数组中,原数组就成为了“垃圾”—— 专业术语才成为“rehash(重hash)”。

loadFactor 的字面翻译为 “负载系数”。可理解为的原数组的装填程度达到这个“负载系数”是,就判定数组已满。loadFactor 越小越耗内存,越大性能越低,当loadFactor越大,及数组越满时,才“重hash”,则越有可能出现链表。

②  HashSet的 存 机制:

(1) 当添加元素时,HashSet会调用该对象的hashCode()方法,得到一个int 值;

(2) 根据hashCode()方法返回的int值,计算出其在底层数组的存储位置(数组中的索引);

(3) 如果要添加元素的位置为空,则直接添加;若不为空,则此处会形成链表。

③ HashSet的 取 机制:

(1) 当添加元素时,HashSet会调用该对象的hashCode()方法,得到一个int 值;

(2) 根据hashCode()方法返回的int值,计算出其在底层数组的存储位置(数组中的索引);

(3) 如果该位置恰好是要取出的元素,就直接取出;如果该位置有链表,,则需要依次搜索链表的元素。

最理想的情况下,HashSet的性能几乎可以匹敌数组,存取性能非常高。

④ HashSet认定对象相等的条件:

   (1) 两个对象的 hashCode()方法返回值相等

   (2) 两个对像通过 equals()方法比较返回true

   —— 这就要求自定义类的hashCode()方法和equals()方法是一致的,要求程序重写equals()方法所用的关键属性,与计算hashCode()方法所用的关键属性相同。

3.TreeSet类:是Set集合类的子接口SortedSet的实现类

  特征:保证Set里面的元素是“大小排序”的。

  ① TreeSet 的底层实现是用标准的“红黑树”存放数据,元素的存入、检索的性能也比较好。

     —— 在HashSet没有大量出现“链表”的情况下,HashSet性能比TreeSet性能好,若是HashSet经常发生“重Hash”,一般选用TreeSetTreeSet不会像HashSet有“空桶”,同时可以保证集合元素是按“大小”排序的。

  ② 使用TreeSet的要求:集合元素必须是可以比较大小的。

     —— Java 比较大小的两种方式:

   (1)  自然排序  —— 所有集合元素实现Comparable 接口。

集合元素实现了 Comparable 接口后,集合元素自身就是可以排 序的;

       (2)  定制排序  —— 要求创建TreeSet时,提供一个Comparator 对象。

Comparator 对象可负责对元素进行比较大小,集合元素无需实现 Compareable 接口,因此集合元素本身是无法排序的。 

  ③ TreeSet相等的判定:只要两个对象通过compareTo()比较返回 0,就表示相等。

示例程序:

import java.util.*;

public class TreeSetTest

{

//本程序演示 TreeSet 对元素的排序

public static void main(String[] args)

{

TreeSet<Integer> set=new TreeSet<>();

//这里的 Integer是对象类型,不能用 int 代替

//其它基本类型与此用法相同

//int型数据会自动装箱成 Integer 对象

set.add(20);

set.add(15);

set.add(48);

set.add(59);

set.add(20);  //重复添加可以通过编译

              //但是运行时只打印一次

System.out.println(set);

TreeSet<String> set2=new TreeSet<>();

set2.add("20");

set2.add("abf");

set2.add("bdg");

set2.add("A");

System.out.println(set2);

}

}

运行结果:

           [15, 20, 48, 59]

           [20, A, abf, bdg]

三.List 集合类(接口)

List 集合提供了大量的“根据索引”来存取元素的方法,由于List可以“根据索引”来存取元素,因此与Set 集合相比,多了一个 “索引遍历”的方法。

① ArrayList 与 Vector 的存储机制:

       (1) 二者底层完全基于数组 —— 对元素的存储完全基于数组实现,因而性能非常快。

       (2) 二者的区别:Vector是从JDK1.0就有的集合,从JDK1.2 后,Sun 公司重写了ArrayList ,替代了原来的 VectorArrayList 是线程不安全的,Vector 是线程安全的,但是 ArrayList 的性能比Vector 要好,在多线程环境下,可以使用Collections 保证ArrayList 为线程安全的。

   ② LinkedList :即使线性表,也是队列,还是栈。

      LinkedList 底层是基于链表实现的,其性能类似于ArrayList

  

      LinkedList 与 ArrayList的比较:

ArrayList :由于可以根据底层数组的索引存取元素,所以性能非常快。但是当插入、删除元素是,插入或删除点后面的元素需要 整体后移 。

LinkedList : 由于底层采用了链表来存储元素,因此根据索引存取元素性能比较慢,但是当插入、删除元素时不需要进行整体后移,此时性能非常快。

示例程序:

import java.util.*;

public class ListTest

{

//本程序演示 List集合的基本方法的使用

public static void main(String[] args)

{

//注意索引是从开始的

List<String> list=new ArrayList<>();

//下面的方法还是当Collection 使用

list.add("Crystal");

list.add("Destiny");

list.add("刘亦菲");

list.add("刘诗诗");

System.out.println(list); 

     //在索引为3的位置插入元素

list.add(3,"刘茜茜");

System.out.println(list);

//替换索引为3的位置的元素

list.set(3,"刘东东");

System.out.println(list);

//删除索引为3的位置的元素

list.remove(3);

System.out.println(list);

//获取List的长度

System.out.println(list.size());

for(int i=0;i<list.size();i++)

{

//获取索引为i的位置的元素

System.out.println(list.get(i));

}

}

}

运行结果:

(注意运行结果的对应关系)

[Crystal, Destiny, 刘亦菲刘诗诗]

[Crystal, Destiny, 刘亦菲刘茜茜刘诗诗]

[Crystal, Destiny, 刘亦菲刘东东刘诗诗]

[Crystal, Destiny, 刘亦菲刘诗诗]

4

Crystal

Destiny

刘亦菲

刘诗诗

三.Queue集合类(接口)

Queue集合类只有一个子接口 ——Deque集合(接口)。

① Deque 集合 是功能被限制了的线性表。

② Deque 集合的两个实现类:

ArrayDeque —— 基于数组实现

LinkedList  —— 基于链表实现

示例程序:

示例1Deque栈的用法(先进后出)

import java.util.*;

public class DequeTest

{

public static void main(String[] args)

{

Deque<String> deque = new ArrayDeque<>();

//将四个元素压入栈中

deque.push("第一个元素");

deque.push("第二个元素");

deque.push("第三个元素");

deque.push("第四个元素");

//调用 pop()方法弹出栈顶元素

//注意元素弹出后就“不再存在于栈里面了”

for(int i=0;i<4;i++)

{

//deque.size()返回元素个数

System.out.println("当前站里面的元素个数是  " + deque.size());

//deque.peek()浏览元素,元素未弹出

System.out.println("   浏览                 " + deque.peek());

//deque.pop()弹出元素

System.out.println("   弹出                 " + deque.pop());

}

      //执行此行代码将抛出异常

      System.out.println( +deque.pop());

}

}

运行结果:

当前站里面的元素个数是  4

   浏览                 第四个元素

   弹出                 第四个元素

当前站里面的元素个数是  3

   浏览                 第三个元素

   弹出                 第三个元素

当前站里面的元素个数是  2

   浏览                 第二个元素

   弹出                 第二个元素

当前站里面的元素个数是  1

   浏览不弹出           第一个元素

   弹出                 第一个元素

Exception in thread "main" java.util.NoSuchElementException 

……

示例2Deque队列的用法(先进先出)

import java.util.*;

public class ListTest

{

public static void main(String[] args)

{

Deque<String> deque = new ArrayDeque<>();

//从队列尾部添加元素

deque.offer("第一个元素");

deque.offer("第二个元素");

deque.offer("第三个元素");

deque.offer("第四个元素");

//从队头取出元素,元素出队后不再存在与队列里

for(int i=0;i<4;i++)

{

System.out.println("当前站里面的元素个数是 " + deque.size());

System.out.println("浏览 " + deque.peek());

System.out.println("取出 " + deque.poll());

}

//元素全部出队后,队列为空(null

System.out.println("已经全部出队 对列为 " + deque.poll());

}

}

运行结果:

当前站里面的元素个数是 4

浏览 第一个元素

取出 第一个元素

当前站里面的元素个数是 3

浏览 第二个元素

取出 第二个元素

当前站里面的元素个数是 2

浏览 第三个元素

取出 第三个元素

当前站里面的元素个数是 1

浏览 第四个元素

取出 第四个元素

已经全部出队 对列为 null

四.操作集合的工具类:Collections

     Collections —— 操作集合的类

 Arrays     —— 操作数组的类

 Objects    —— 操作对象的类

 

 Collections 的重要方法:

shuffle(List<?> list)     —— 将List 集合元素进行随机排列

synchronizedXxx       —— 这个系列(Xxx不同)的方法是把原有的集合包装成线程安全的集合

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值