转载请注明源出处:http://www.cnblogs.com/lighten/p/7278655.html

1.前言

  从本章开始介绍Java的集合类,这些类主要存在于java.util包下,该系列基于JDK8,类中所包含的JDK8的lambda表达式的相关内容不进行介绍,只关注集合本身的使用方法。

2.集合体系

  

  上图就是Java中的集合主要层次结构了,所有的集合都需要实现Iterable<T>接口,最上层的是通用的Collection接口定义,然后就是较为熟悉的三种结构:List、Queue和Set了。下面又根据不同的特性有了子类接口。右图就是相关的抽象实现了,所有具体的类都会对应继承这些抽象实现。Map不在本章讨论范围内,之后涉及到的时候会先讲解Map的实现。

3.接口定义和部分实现

3.1 Collection

  上图是JDK8中集合的接口定义,不关注JDK8的新特性,有如下接口:

  1.size():集合中元素的个数

  2.isEmpty():集合是否为空

  3.contain(Object):集合是否包含某个元素

  4.iterator():获取集合的迭代器

  5.toArray():返回集合中的元素数组

  6.toArray(T[]):将集合中的元素放入所给数组中,如果所给数组大于集合大小,补充null。如果数组小于集合大小,返回数组大小的集合元素(实际集合元素个数小于数组大小依旧补充null)。

  7.add(E):向集合中添加一个元素

  8.remove(Object):在集合中移除指定的元素

  9.containsAll(Collection<?>):集合是否包含指定集合的全部元素,有一个没有就返回false

  10.addAll(Collection<?>):将指定的集合中全部的元素添加到该集合中,返回值的含义并不是全部成功,而是集合的元素有所改变就是true.(做并集A∪B)

  11.removeAll(Collection<?>):将指定的集合中全部的元素都从该集合中移除,返回值的含义是移除操作造成该集合有所改变就是true。(A-A∩B)

  12.retainAll(Collection<?>):这个方法和removeAll相反,其含义是该集合只保留指定集合中的元素,移除其它元素,有改变就是true。(实际就是做交集,保留交集部分A∩B)

  上述方法就是每一个集合所必备的相关方法。AbstractCollection抽象类中,几乎实现了所有的接口方法,除了以下三个:size()、iterator()和add()方法,其它方法的实现都是基于这三个抽象方法的(add不是抽象方法,其直接抛出异常,需要子类覆盖,所以此处也视为抽象方法)。当然,实现的方法也许在子类中会被覆盖,不过也基本是实现完了可以实现的功能。

3.2 List

  List接口继承自Collection接口。除了Collection接口的方法外,还增加了以下与位置相关的方法:

  1.get(int):获取指定位置的元素

  2.set(int,E):替换指定位置的元素

  3.add(int,E):将元素插入指定位置

  4.remove(int):移除指定位置的元素

  5.indexOf(Object):返回指定元素第一次在list中出现的位置,没有就是-1

  6.lastIndexOf(Object):返回指定元素最后一次在list中出现的位置,没有就是-1

  7.listIterator():返回一个list类型的迭代器,比一般的迭代器提供了前移的方法

  8.listIterator(int):返回一个从指定位置开始的list的list类型迭代器。

  9.subList(int,int):返回一个子list,范围是[start,end)

  10.addAll(int, Collection):将一个集合中的元素从指定位置开始全部插入

  list接口的抽象类AbstractList也是对应的继承了AbstractCollection类,当然也需要实现list接口。对于AbstractCollection中实现的方法,AbstractList大体没有变化,除了add(E)和iterator()方法其有具体实现了。add(E)方法是通过add(int,E)方法实现的,其它与位置有关list接口定义的方法都没有实现,需要具体子类去覆盖实现。其它值得一提的方法有indexOf和lastIndexOf,clear()等方法,其实现都是通过listIterator()迭代器完成的,而不是一般的迭代器。而后重要的就是三个实现类了:Itr、ListItr和SubList。

  Itr这个普通的迭代器的内容很简单,就如上图。cursor是当前读取的元素下标,所以hasNext的判断就是其不等于list大小就是true。lastRet是记录上一个位置,原因是调用next的时候cursor会自增1,这个时候remove方法就得需要上一次的位置才能删除当前对象。expectedModCount是用来判断并发修改的,迭代器虽然允许边遍历边删除,但是并不允许并发遍历删除。了解了这个,其实现也就很好理解:

  ListItr的实现是继承了Itr类的,其就是增加了前移操作和set、add操作,操作也依旧容易,根据Itr的原理,只需要处理cursor和lastRet就可以了。

  set和add方法就是通过当前位置来调用list的相关方法完成。

  SubList是直接继承自AbstractList类的,其接受一个list,和起始,终止坐标。但是要注意的是,SubList持有的是传入的list的引用,对SubList进行修改操作都会影响原list的内容,其只是限定了一下操作边界而已,并不是真正意义上的一个新的拷贝list。并且多线程操作sublist是不允许的,按照代码来看,多线程操作不同的sublist,这些sublist持有同一个list也是不被允许的。

    @Test
public void test() {
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 5; i++) {
list.add(i);
}
List<Integer> sub = list.subList(1, 3);
sub.set(0, 100);
System.out.println(Arrays.toString(list.toArray()));
}

测试多线程的情况:

    @Test
public void test2() throws InterruptedException {
int threadNum = 3;
int all = 10000;
List<Integer> list = new ArrayList<>();
for(int i = 0; i < all; i++) {
list.add(i);
}
int per = all / threadNum;
CountDownLatch latch = new CountDownLatch(threadNum);
ExecutorService service = Executors.newCachedThreadPool();
CyclicBarrier barrier = new CyclicBarrier(threadNum);
for(int i = 0; i < threadNum; i++) {
service.submit(new TestTask(list.subList(i*per, (i+1)*per), barrier, latch));
}
latch.await();
} class TestTask implements Runnable { private List<Integer> sub;
private CyclicBarrier barrier;
private CountDownLatch latch; public TestTask(List<Integer> sub, CyclicBarrier barrier, CountDownLatch latch) {
this.sub = sub;
this.barrier = barrier;
this.latch = latch;
} public TestTask(List<Integer> sub, CountDownLatch latch) {
this.sub = sub;
this.latch = latch;
} @Override
public void run() {
try {
if(barrier != null) {
barrier.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
try {
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < sub.size(); i++) {
sub.remove(i);
}
System.out.println(Thread.currentThread().getName()+" over!");
} catch(Throwable e) {
e.printStackTrace();
} finally {
latch.countDown();
}
} }

  这个测试实际上并不规范,第一个实际运行的时候没有模拟出并发,看允许还是一个个线程执行的,第二个是sublist并不是抽象父类中的sublist,ArrayList重写了这个sublist。但还是可以参考一下。

3.3 Queue

  Queue队列结构也是继承了Collection接口,上图是其独自定义的一些方法。

  1.add(E):添加一个元素入队列,队列有容量限制时,超过容量抛出异常

  2.offer(E):添加一个元素入队列,在队列有容量限制的时候比add方法更好,不会抛出异常

  3.remove():检索并移除队列头,与poll不一样的地方在于如果队列为空,抛出异常

  4.poll():检索并移除队列头,队列为空返回NULL

  5.element():检索不移除,返回队列头,队列为空抛出异常

  6.peek():检索不移除,返回队列头,队列为空返回NULL

  AbstractQueue继承了AbstractCollection类,并实现Queue接口。其实现了add、remove和element方法,做法是借助未实现的offer、poll和peek方法,没有什么可说的地方。

3.4 Set

  Set接口继承了Collection,并没有添加新的方法。其抽象实现类AbstractSet也没有做什么改变,AbstractCollection未实现的add,size,iterator均没有实现,只是重写了一下removeAll方法,减少了一下迭代次数而已。

Java之集合(一)接口及抽象类的更多相关文章

  1. Java集合-07Map接口及其抽象类

    简介 前面把List基本记录完了,对于集合List,Map,Set,因为Set基于Map,故先记录Map. 这一篇主要记录Map接口及其抽象类(java version:1.8) 整体架构 参考上图, ...

  2. 1)Java学习笔记:接口和抽象类的异同

    Java接口和抽象类很像,他们有哪些相同点和异同点呢,下面我们做一个小结 相同 ① 都不能被实例化,都位于继承树的顶端,用于被实现或者继承 ② 都可以包含抽象方法,实现接口或者继承抽象类的普通子类都必 ...

  3. 学JAVA第十八天,接口与抽象类进一步加深

    昨天老师讲了建网站,还要交钱买东西的,所以就没写,今天讲了接口与抽象类进一步加深 上完今天的课后,我才知道一个接口可以有多个实现类,一个实现类可以同时接多个接口. 现在就用代码来解释吧!!! 举例用人 ...

  4. Java学习笔记之接口和抽象类

    接口(interface)1.interface创建一个接口,implements实现接口 interface jiekou{} class lie implements jiekou{}2.接口可以 ...

  5. 【知了堂学习笔记】java 接口与抽象类

    本次主角:抽象类 .接口. 对于皮皮潇这样一类的Java初学者来说,接口和抽象类如果不去花大量的精力与时间是很难弄清楚的,而我也是在最近这周的项目学习中感觉到了我对这两个概念不熟悉,所以导致对一些问题 ...

  6. C++虚函数virtual,纯虚函数pure virtual和Java抽象函数abstract,接口interface与抽象类abstract class的比较

    由于C++和Java都是面向对象的编程语言,它们的多态性就分别靠虚函数和抽象函数来实现. C++的虚函数可以在子类中重写,调用是根据实际的对象来判别的,而不是通过指针类型(普通函数的调用是根据当前指针 ...

  7. Java之集合(七)Map

    转载请注明源出处:http://www.cnblogs.com/lighten/p/7327216.html 1.前言 按照顺序,本章本是要对Set的相关类进行介绍及讲解的.但是对于其实现有所了解的都 ...

  8. Java接口和抽象类的区别

    今天看到项目中,写了一个抽象类,里面有很多方法继承了这类,当调用这个接口时,采用的是这个抽象类去调方法的,当时一想,这个不就是我们说的Java的多态的特征: 继承:存在继承关系的子类和父类 重写:子类 ...

  9. [JAVA设计模式]第一部分:接口、抽象类、设计原则

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

随机推荐

  1. 20. Dog,Man's Best Friend 狗,人类最好的朋友

    . Dog,Man's Best Friend 狗,人类最好的朋友 ①The dogs has always been considered man's best friend.Always note ...

  2. Django入门指南-第6章:第一个视图函数(完结)

    http://127.0.0.1:8000/ # boards/views.py from django.http import HttpResponse from .models import Bo ...

  3. python 求最大子序列

     动态规划的本质,是对问题状态的定义和状态转移方程的定义.dynamic programming is a method for solving a complex problem by breaki ...

  4. OpenGL ES 光照模型之——环境光照(RenderMonkey测试)

    概述及目录(版权所有,请勿转载 www.cnblogs.com/feng-sc/) 本文总结如何在RenderMonkey下做简单的OpenGL ES环境光光照模型测试. 主要包括如下内容: 1.使用 ...

  5. WC Java 实现

    项目 github 地址 一. 实现情况 基本要求 c 统计文件字符数 (实现) w 统计文件词数 (实现) l 统计文件行数(实现) 扩展功能 s 递归处理目录下符合条件得文件(实现) a 返回文件 ...

  6. Java程序性能定位工具-火焰图

    Java程序性能定位工具-火焰图 前言 Java火焰图是一种新的查看CPU利用率方式.今天就带大家一起使用来自Google大神的工具来生成火焰图.火焰图非常的直观,问题一目了然,希望有一天它能成为JA ...

  7. .NET 调试入门(三)常用的命令

    windbg ANSI Command Tree 1.0 title {"Crash Dump Analysis Checklist"} body {"Crash Dum ...

  8. INNER JOIN与LEFT JOIN在SQL Server的性能

    我创建了INNER JOIN 9桌,反正需要很长的(超过五分钟).所以,我的民歌改变INNER JOIN来LEFT JOIN LEFT JOIN的性能较好,在首次尽管我所知道的.之后我变了,查询的速度 ...

  9. ExceptionLess ASP.NET MVC 异常日志框架

    Exceptionless 一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web API,Web Forms,WPF,Console,ASP.NET MVC ...

  10. CentOS ASP.NET Core Runtime Jexus跨平台布署

    .net core 开源和跨平台,能布署到当前主流的Windows,Linux,macOS 系统上.本篇我们将在 Linux 系统上使用 ASP.NET Core Runtime 和 Jexus 布署 ...