博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java学习——Collection集合
阅读量:3941 次
发布时间:2019-05-24

本文共 6705 字,大约阅读时间需要 22 分钟。

Java学习——Collection集合

今天我们来学习Collection集合,学习这个集合之前我们先要知道为什么要引入集合。我们都直到Java语言是一种面向对象的语言,所以为了存取对象方便,就引入了集合的概念。

那么集合和数组到底又有什么区别呢?

  • 长度区别:数组的长度一旦定义就不可变的;但是集合的长度是可变的,是可以自动扩容的
  • 存储的数据类型区别:我们知道数组是可以存储基本数据类型也可以存储引用数据类型;但是集合只能存储引用数据类型(当然我们Java语言有自动拆箱和自动装箱,这个存储的数据类型是无法限制集合的。比如我们想要存储int类型的数据,Java语言就会为我们自动装箱成Integer类型的数据存入,取的时候道理相同)
  • 存的内容种类区别:数组只能存一种数据类型类型的数据;而集合可以存储多种数据类型的数据

了解了集合的基本概念以后,我们也必须要掌握常用的Collection集合的继承体系,如下:

在这里插入图片描述
在Collection中我们最常用的就是List集合和Set集合这两种集合,那么就先要只知道顶层父类的方法:

  • boolean add(Object obj):添加一个元素
  • boolean addAll(Collection c):添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
  • void clear():移除所有元素
  • boolean remove(Object o):移除一个元素
  • boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素两个集合的交集元素,如果没有交集元素 则删除失败 返回false
  • boolean contains(Object o):判断集合中是否包含指定的元素
  • boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
  • boolean isEmpty():判断集合是否为空
  • Iterator iterator():获取集合的迭代器对象
  • int size():获取元素的个数
  • boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
  • Object[] toArray():把集合转换为数组

这些方法简单易懂,就不做详细的解释了

当然子类的方法会更加丰富,现在我们就先从List这个分支学起:

一、 List

List集合的特点:元素有序,并且每一个元素都存在一个索引,元素可以重复

1.ArrayList

ArrayList集合的底层数据结构是数组,查询快,增删慢;线程不安全,效率高

2.Vector

Vector集合底层数据结构是数组,查询快,增删慢。线程安全,效率低

Vector集合线程安全是因为它底层源码都用synchronized关键字所修饰

3.LinkedList

LinkedList集合底层数据结构是链表,查询慢,增删快,线程不安全,效率高

下面我们来看看使用迭代器对象遍历集合:

public class Test {    public static void main(String[] args) {        //创建ArrayList集合对象,泛型定为Integer类型        ArrayList
list = new ArrayList<>(); //向集合中添加元素 list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.add(7); list.add(8); list.add(9); list.add(10); //获取Collection集合的父类迭代器对象 Iterator
iterator = list.iterator(); //iterator.hasNext()判断下一个是否有元素 while (iterator.hasNext()){ //拿出下个元素,并打印 Integer next = iterator.next(); System.out.println(next); } }}/** * 输出结果:1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 */

当然List集合也有它特有的迭代器对象,listIterator,也都是一样的用法。

下来我们来看用迭代器对象遍历集合的时候,如果往集合中增加元素,会产生一个异常:

public class Test {    public static void main(String[] args) {        //创建ArrayList集合对象,泛型为Integer类型        ArrayList
list = new ArrayList<>(); //向集合中添加元素 list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.add(7); list.add(8); list.add(9); list.add(10); //获取Collection集合的父类迭代器对象 Iterator
iterator = list.iterator(); //iterator.hasNext()判断下一个是否有元素 while (iterator.hasNext()){ //拿出元素 Integer next = iterator.next(); if (next==5){ list.add(100); } System.out.println(next); } }}
输出:				1			2			3			4			5			Exception in thread "main" java.util.ConcurrentModificationException				at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)				at java.util.ArrayList$Itr.next(ArrayList.java:851)				at cn.xiyou.Test.main(Test.java:26)

ConcurrentModificationException并发修改异常,产生这个异常的原因是因为使用迭代器进行遍历的时候,迭代器会计算好集合的长度,但是你在迭代的过程中添加元素,集合长度改变,迭代器就不知道长度为多少了,就会出现并发修改异常。

那么解决的办法有两个:

  1. 使用迭代器特有的add方法去添加元素
  2. 使用for循环遍历集合

这里我们介绍一种新式的for循环:

public class Test {    public static void main(String[] args) {        //创建ArrayList集合对象,泛型为Integer类型        ArrayList
list = new ArrayList<>(); //向集合中添加元素 list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.add(7); list.add(8); list.add(9); list.add(10); //新式for循环遍历集合 for (Integer i : list) { System.out.println(i); } }}

二、Set

Set集合的特点:元素无序(存取的顺序不一致)且唯一

1.HashSet

HashSet的底层数据结构是哈希表(JDK1.7之前:链表+数组+红黑树;JDK1.7之后:链表+数组+红黑树),线程不安全,可以存null值。

那么HashSet集合是如何保证元素唯一性的呢?

为了保证HashSet集合的元素唯一性,HashSet集合必须要重写hashCode()和equals()方法。
1.当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据算出来的hashCode值去确定该对象在HashSet中的存储位置。
2.当两个对象的hashCode值相等时,我们会重写equals()方法,让两个对象去比较其内容,如果不一致则存储,如果一致则不存储
所以,要保证HashSet集合元素唯一就必须重写hashCode()和equals()方法。

2.LinkedHashSet

LinkedHashSet底层数据结构是哈希表+链表。链表保证元素有序,哈希表保证元素唯一。

3.TreeSet

TreeSet底层数据结构是二叉树,保证了元素有序

那么在TreeSet中有两种排序方式:

1). 自然排序

比较的对象要实现Comparable接口并重写该接口中compareTo方法,如下:

//实现Comparable接口,并将泛型定为Studentpublic class Student implements Comparable
{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(Student student) { //以姓名的字典顺序排序,如果姓名一样,则以年龄大小排序 int num = student.name.compareTo(this.name); int num2 = num==0?student.age-this.age:num; return num2; }}

然后新建一个测试类,使用TreeSet集合添加元素,遍历显示结果

public class Test {    public static void main(String[] args) {    	//创建TreeSet集合并存储Student对象        TreeSet
set = new TreeSet<>(); set.add(new Student("张三",23)); set.add(new Student("李四",24)); set.add(new Student("王五",25)); set.add(new Student("赵六",26)); set.add(new Student("田七",27)); set.add(new Student("牛二",28)); //遍历集合,查看自然排序结果 for (Student student : set) { System.out.println(student.getName()+"=="+student.getAge()); } }}

结果:

赵六==26田七==27王五==25牛二==28李四==24张三==23

2). 比较器排序

比较器排序就比较简单了,比较的类不用实现任何接口,直接向TreeSet集合中传入一个比较器Comparator即可:

public class Test {    public static void main(String[] args) {   		 //创建TreeSet集合并传入一个Comparator比较器,然后重写compare方法        TreeSet
set = new TreeSet<>(new Comparator
() { @Override public int compare(Student s1, Student s2) { int num = s1.getName().compareTo(s2.getName()); int num2 = num==0?s1.getAge()-s2.getAge():num; return num2; } }); //向集合中存入对象 set.add(new Student("张三",23)); set.add(new Student("李四",24)); set.add(new Student("王五",25)); set.add(new Student("赵六",26)); set.add(new Student("田七",27)); set.add(new Student("牛二",28)); //遍历集合看结果 for (Student student : set) { System.out.println(student.getName()+"=="+student.getAge()); } }}

结果:

张三==23李四==24牛二==28王五==25田七==27赵六==26

我们可以看到,比较器排序与自然排序的结果是一样的,在我们平时,建议使用比较器排序

集合的学习是为了以后在编码中选取更合适的集合去存储数据,后面我们还会学到map集合,敬请期待哦!

转载地址:http://lxiwi.baihongyu.com/

你可能感兴趣的文章
TAUCS库的编译(vs2010)
查看>>
color vector using in plotting example points and lines between corresponding vertices
查看>>
mex 里面调用matlab函数
查看>>
matlab中cuda编程中分配grid和block dimension的时候的注意事项
查看>>
GPU CUDA and MEX Programming
查看>>
arrayfun用法
查看>>
矩阵积分
查看>>
optimization on macOS
查看>>
Template-Based 3D Model Fitting Using Dual-Domain Relaxation
查看>>
install libfreenect2 on ubuntu 16.04
查看>>
how to use automake to build files
查看>>
using matlab drawing line graph for latex
查看>>
How package finding works
查看>>
build opencv3.3.0 with VTK8.0, CUDA9.0 on ubuntu9.0
查看>>
how to compile kinfu_remake with cuda 9.0 opencv2.4.13.4
查看>>
qtcreator4.4.1中cmake 与cmake3.5.1本身generate出来的setting是有区别的解决方法
查看>>
ubuntu下解决csdn网页打不开的问题
查看>>
MySQL server has gone away 问题的解决方法
查看>>
MySQL十大优化技巧
查看>>
PHP中文件读写操作
查看>>