栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA之集合

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA之集合

write:2022-3-14

文章目录

集合集合的分类Collection接口

集合操作方法(针对单个元素)集合的批量操作遍历集合元素自动装箱与拆箱 Map接口四种集合详讲

Set(集)List(列表)Queue(队列)

普通队列双向队列 Deque Map(映射) 线程安全的集合

集合

数组与集合的区别

    数组的长度是固定的(数组用new语句创建后,长度一般是固定的);集合中的元素的数目可以变化。数组可以存放基本类型的数据,也可以存放引用类型的数据;集合中不能存放基本类型数据,而只能存放对象的引用。数组本身没有操纵元素的方法(只有一个length属性);所有Java集合类都位于java.util包中。Java集合类具有各种操纵集合中元素的方法。
集合的分类

    集合有四种:
    Set(集):集合中的对象不按特定方式排序,并且没有重复对象。它的有些实现类能对集合中对象按特定方式排序。(无序不重复)
    List(列表):集合中的对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象。List与数组有些相似。(有序可重复)
    Queue(队列):集合中的对象按照先进先出的规则来排列。在队列的末尾添加元素,在队列的头部删除元素。可以有重复对象。双向队列则允许在队列的末尾和头部添加和删除元素。(用于模拟队列这种数据结构)
    Map(映射):集合中的每一个元素包含一对键(Key)对象和值(Value)对象,集合中没有重复的键对象,值对象可以重复。它的有些实现类能对集合中的键对象进行排序。(代表具有映射关系的集合)

    以上四类集合可用下图进行理解:

    主要的集合接口和类:
    集合类都位于java.util包下,Queue接口,Set接口,List接口是collection接口的子类,其又各有子类
    Map接口没有父类,有子类
    用以下类图来表示:

Collection接口

Queue接口,,Set接口,List接口是collection接口的子类,其又各有子类或者子接口

集合操作方法(针对单个元素)

collection接口中声明了一些对集合的基本操作:

集合的批量操作

在Collection接口中定义了以下方法:
(1)boolean retainAll(Collection c)
修改当前集合,在当前集合中保留那些同时位于参数c集合中的元素,删除其余的元素。如果当前集合最终做了改动,就返回true。
(2)boolean removeAll(Collection c)
删除当前集合中的那些同时位于参数c集合中的元素。
(3)boolean addAll(Collection c)
把参数c集合中的元素加入到当前集合中。
(4)boolean containsAll(Collection c)
判断当前集合中是否存在参数c集合中的元素。

遍历集合元素

Collection接口的iterator() 方法用于获得集合中的所有元素,返回一个Iterator对象。

Iterator接口隐藏底层集合的数据结构,向客户程序提供了遍历各种类型的集合的统一接口。Iterator接口中声明了如下方法:
hasNext():判断集合中的元素是否遍历完毕,如果没有,就返回true。
next():返回下一个元素。
remove():从集合中删除由next()方法返回的当前元素。

自动装箱与拆箱

JDK的高版本会有,省去基本类型与对象转换的操作,方便编程;

Map接口

四种集合详讲 Set(集)

Set(集):集合中的对象不按特定方式排序,并且没有重复对象。它的有些实现类能对集合中对象按特定方式排序。

    Set集合中存放的是对象的引用,并且没有重复对象。
    eg:
Set set = new HashSet();   //<>是一个泛型标记,里面的是数据类型
String s1 = new String("Hello");
String s2 = s1;
String s3 = new String("world");
set.add(s1);
set.add(s2);
set.add(s3);

打印结果:2(因为s1和s2是同一个对象)

    Set类的一个实现类:HashSet类
    1)HashSet类按照哈希算法来存取集合中的对象,具有很好的存取和查找性能(效率高)。当向集合中加入一个对象时,HashSet会调用对象的hashCode()方法获得哈希码,然后根据这个哈希码进一步计算出对象在集合中的存放位置。
    2)在Object类中定义了hashCode()和equals()方法。为了保证HashSet能正常工作,要求当两个对象用equals()方法比较的结果为true时,它们的哈希码也相等。

例如,如果customer1.equals(customer2)为true,那么以下表达式的结果也应该是true:
customer1.hashCode()==customer2.hashCode()

    Set类的一个实现类:TreeSet类
    TreeSet类实现了SortedSet接口(SortedSet接口也是Set的子类),能够对集合中的对象进行排序。

1)TreeSet能够对数字进行由小到大排序(即自然排序)
eg:

Set set=new TreeSet();
set.add(8);  //自动装箱,把8转换为相应的Integer对象,再加入到Set中
set.add(7);  
set.add(6);
set.add(9);
 
for(int i:set) //自动拆箱,把集合中的Integer对象转换为int基本类型数据
  System.out.print(i+" ");

以上程序的打印结果为:6 7 8 9

2)除了自然排序,TreeSet还支持客户化排序。
java.util.Comparator接口提供具体的排序方式,指定被比较的对象的类型,Comparator有个compare(T x, T y)方法,用于比较两个对象的大小。
当compare(x,y)的返回值大于0,表示x大于y;
当compare(x,y)的返回值小于0,表示x小于y;
当compare(x,y)的返回值等于0,表示x等于y。

List(列表)

List(列表):集合中的对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象。List与数组有些相似。(看情况二选一选取使用)

    主要实现类之一:ArrayList类:
    ArrayList:ArrayList代表长度可变的数组。允许对元素进行快速地随机访问(给定索引 进行访问),但是向ArrayList中插入与删除元素的速度较慢。

    主要实现类之一:linkedList类:
    linkedList:在实现中采用链表数据结构。对顺序访问进行了优化,向List中插入和删除元素的速度较快,随机访问则相对较慢。随机访问是指检索位于特定索引位置的元素。linkedList单独具有addFirst()、addLast()、getFirst()、getLast()、removeFirst()和removeLast()方法,这些方法使得linkedList可以作为堆栈、队列和双向队列使用。

    List访问列表中的元素:
    List中的对象按照索引位置排序,客户程序可以按照对象在集合中的索引位置来检索对象。
    List的get(int index)方法返回集合中由参数index指定的索引位置的对象,第一个加入到集合中的对象的索引位置为0。

List list=new ArrayList();
list.add(3);  //自动装箱,把3转换为相应的Integer对象,再把它加入到List中
list.add(4);
list.add(3);
list.add(2);

for(int i=0;i 

以上程序的打印结果为:3 4 3 2

    Collections类的sort()排序方法
    List只能对集合中的对象按索引位置排序,如果希望对List中的对象按其他特定方式排序,可以借助Comparator接口和Collections类。
    Collections类是Java集合类库中的辅助类,它提供了操纵集合的各种静态方法,其中sort()方法用于对List中的对象进行排序:
    sort(List list):对List中的对象进行自然排序。

以下程序对List中的Integer对象进行自然排序:

List list=new ArrayList();
list.add(new Integer(3));
list.add(new Integer(4));
list.add(new Integer(3));
list.add(new Integer(2));
 
Collections.sort(list);  //为列表中的元素进行排序
for(Integer i:list)
  System.out.print(i+" ");

以上程序的打印结果为:2 3 3 4
sort(List list,Comparator comparator):对List中的对象进行客户化排序,comparator参数指定排序方式。

    把数组包装成List对象
    java.util.Arrays类的asList()方法能够把一个Java数组包装为一个List对象,这个List对象代表固定长度的数组。
    所有对List对象的操作都会被作用到底层的Java数组。由于数组的长度不能改变,因此不能调用这种List对象的add()和remove()方法,否则会抛出java.lang.UnsupportedOperationException运行时异常。
String[] ss={"Tom","Mike","Jack"};
List list=Arrays.asList(ss);
list.set(0,"Jane");  //合法,可以修改某个位置的元素
System.out.println(Arrays.toString(ss));  //打印[Jane, Mike, Jack]
 
//list.remove("Mike");  运行时会抛出java.lang.UnsupportedOperationException

//list.add("Mary");  运行时会抛出java.lang.UnsupportedOperationException
    在List接口中还有一个用于获得子列表视图的方法:
    List subList(int fromIndex,int toIndex)

以上方法中的fromIndex参数和toIndex参数分别指定元素的起始索引和结束索引。起始索引对应的元素会加入到子列表中,而结束索引对应的元素不会加入到子列表中。例如list.subList(0,7)将把当前列表中索引从0到6的元素加入到子列表中。

Queue(队列)

Queue(队列):集合中的对象按照先进先出的规则来排列。在队列的末尾添加元素,在队列的头部删除元素。可以有重复对象。双向队列则允许在队列的末尾和头部添加和删除元素。
多数人都有过在火车站售票大厅排队等待购票的经历。后加入的人排在队列的末尾,排在队列头部的人优先购票后离开队列。
从JDK5开始,用java.util.Queue接口来表示队列。队列的特点是向末尾添加元素,从队列头部删除元素,队列中允许有重复元素。

普通队列

(1)Queue接口具有以下加入元素的方法:
boolean add(E element)
boolean offer(E element)
以上两个方法都向队列的末尾添加元素,如果操作成功就返回true。参数的类型“E”为泛型类型。这两个方法的区别在于,如果队列已满,add()方法会抛出IllegalStateException,而offer()方法返回false。
(2)Queue接口具有以下删除元素的方法:
E remove()
E poll()
以上两个方法都会删除队列头部的元素。这两个方法的区别在于,如果队列为空,remove()方法抛出NoSuchElementException,而poll()方法返回null。
(3)Queue接口具有以下获取元素的方法:
E element()
E peek()
以上两个方法都会返回队列头部的元素,但不删除它。这两个方法的区别在于,如果队列为空,element()方法抛出NoSuchElementException,而peek()方法返回null。

双向队列 Deque

Queue接口是单向队列,它有一个子接口Deque,表示双向队列。双向队列的特点是在队列的头部和末尾都可以添加或删除元素。

(1)Deque接口具有以下向队列头部或末尾添加元素的方法:
void addFirst(E element)
void addLast(E element)
boolean offerFirst(E element)
boolean offerLast(E element)
如果队列已满,前两个方法抛出IllegalStateException,而后两个方法返回false。
(2)Deque接口具有以下从队列头部或末尾删除元素的方法:
E removeFirst()
E removeLast()
E pollFirst()
E pollLast()
如果队列为空,前两个方法抛出NoSuchElementException,而后两个方法返回null。
(3)Deque接口具有以下从队列头部或末尾获取元素(不会删除该元素)的方法:
E getFirst()
E getLast()
E peekFirst()
E peekLast()
如果队列为空,前两个方法抛出NoSuchElementException,而后两个方法返回null。

import java.util.*;
public class DequeTester{
  public static void main(String args[]){
    Deque queue=new ArrayDeque();
    queue.add("老二"); //向队列末尾添加元素
    queue.addFirst("老大"); //向队列头部添加元素
    queue.addLast("老三"); //向队列末尾添加元素
    queue.add("老四");  //向队列末尾添加元素
 
    System.out.print("遍历双向队列:");
    for(String e:queue )
      System.out.print(e+" ");
 
    System.out.println("n删除双向队列的最后一个元素:"+queue.removeLast());  
  }
}

打印结果如下:

遍历双向队列:老大 老二 老三 老四
删除双向队列的最后一个元素:老四

Map(映射)

Map(映射):集合中的每一个元素包含一对键(Key)对象和值(Value)对象,集合中没有重复的键对象,值对象可以重复。它的有些实现类能对集合中的键对象进行排序。
Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象。

    向Map集合中加入元素时,必须提供一对键对象和值对象。
    从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
    eg:以下程序通过Map的put(Object key,Object value)方法向集合中加入元素,通过Map的get(Object key)方法来检索与键对象对应的值对象:
Map map=new HashMap();
map.put("1","Monday");
map.put("2","Tuesday");
map.put("3","Wendsday");
map.put("4","Thursday");
 
String day=map.get("2");  //day的值为“Tuesday”
    遍历映射
Map map=new HashMap();
map.put("1","Mon.");
map.put("1","Monday");
map.put("one","Monday");
 
Set> set=map.entrySet();    //将Map用entrySet方法转换成Set,entrySet取出的是每一个元素即键值对
for(Map.Entry entry : set)  //entry表示Map中的一对键与值
  System.out.println(entry.getKey()+":"+entry.getValue());

由于第一次和第二次加入Map中的键对象都为“1”,因此第一次加入的值对象将被覆盖,Map集合中最后只有两个元素,分别为:
“1”对应“Monday”
“one”对应“Monday”

    主要实现类之一:HashMap
    HashMap按照哈希算法来存取键对象,有很好的存取性能,为了保证HashMap能正常工作,和HashSet一样,要求当两个键对象通过equals()方法比较为true时,这两个键对象的hashCode()方法返回的哈希码也一样。

    主要实现类之一:TressMap
    TreeMap实现了SortedMap接口,能对键对象进行排序。和TreeSet一样,TreeMap也支持自然排序和客户化排序两种方式。
    1)自然排序

Map map=new TreeMap();
map.put("1","Monday");
map.put("3","Wednesday");
map.put("4","Thursday");
map.put("2","Tuesday");
 
Set keys=map.keySet();   //keySet取出的是每一个键对象
for(String key:keys){
  String value=map.get(key);
  System.out.println(key+" "+value);
}

Map的keySet()方法返回集合中所有键对象的集合,程序的打印结果为:
1 Monday
2 Tuesday
3 Wednesday
4 Thursday

线程安全的集合

在多线程环境中,可能会有多个线程同时操纵同一个集合,比如一个线程在为集合排序,而另一个线程在不断向集合中加入新的元素。
为了避免并发问题,可以采取以下几种解决措施:
(1)在程序中对可能导致并发问题的代码块进行同步。
(2)利用Collections的synchronizedXXX()方法获得原始集合的同步版本:
Collection synchronizedCollection=
Collections.synchronizedCollection(originalCollection);
程序中确保所有线程只对这个采取了同步措施的集合对象操作。
(3)如果集合只包含单个元素并且不允许被修改,可以用Collections的singletonXXX()方法来构造这样的集合,这可以避免集合被线程错误地修改,而且由于不必采取同步措施,可以提高并发性能。
(4)如果集合的元素不允许被修改,可以用Collections的unmodifiableXXX()方法来生成原始的集合视图,让线程只访问这个集合视图,这可以避免集合被线程错误地修改,而且由于不必采取同步措施,可以提高并发性能。
(5)利用Collections的synchronizedXXX()方法获得原始集合的同步版本后,如果一个线程操纵集合的同步版本,而另一个线程操纵原始的集合,那么仍然会导致并发问题。

为了避免这种情况,可以直接采用java.util.concurrent并发包提供的线程安全的集合,例如:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet和ConcurrentlinkedQueue。这些集合的底层实现采用了复杂的算法,保证多线程访问集合时,既能保证线程之间的同步,又具有高效的并发性能。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763986.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号