集合类

Java类集

我们知道数组最大的缺陷就是:长度固定。从jdk1.2开始为了解决数组长度固定的问题,就提供了动态对象数组实现框架——Java类集框架。Java集合类框架其实就是Java针对于数据结构的一种实现。

Java类集的本质就是动态对象数组。

在Java类集中提供有两个最为核心的接口:Collection和Map接口。

1、Collection接口

(1)定义:

public interface Collection<E> extends Iterable<E>

Collection是单个集合保存的最大接口。

Collection与写过的链表类似,每一次进行数据操作的时候只能对单个对象进行处理。且从jdk1.5开始追加泛型应用,这样可以避免ClassCastException异常的出现,里面的所有保存数据类型应该相同。

(2)常用方法

向集合中添加元素:boolean add(E e)

向集合中添加一组元素:boolean addAll(Collection<? extends E> c)

清空集合数据: void clear()

查找数据是否存在:boolean contains(Object o)

删除数据:boolean remove(Object o)

取得集合长度:int size()

将结合变为对象数组:Object[] toArray()

取得Iterator接口对象,用于集合输出:Iterator<E> iterator()

实则Collection接口只是一个存储数据的标准,并不能用来区分存储类型。如:需要区分可存储数据的重复与否。所以我们一般用来使用的是Collection的两个子接口:List和Set。

2、List接口

public interface List<E> extends Collection<E>

新增方法:

根据索引取得保存数据: E get(int index)

修改数据: E set(int index, E element)

List接口与Collection接口相比,比其增加了一个get()、set()方法,可以通过指定的索引值取得修改、内容。要想取得接口的实例化对象则其必须有子类,在List接口下有三个常用子类:ArrayList、Vector、LinkedList.

(1)ArrayList

public class ArrayList<E> extends AbstractList<E>

ArrayList是针对于List的数组实现。


  1. package mycollection;
  2. import java.util.*;
  3. public class Test {
  4. public static void main(String[] args) {
  5. //这时候集合中只能存String类型的数据
  6. List<String> list = new ArrayList<>();
  7. list.add("hello");
  8. list.add("world");
  9. //添加重复元素
  10. list.add("hello");
  11. list.add("陕科大");
  12. System.out.println(list);
  13. //返回集合中元素的个数
  14. System.out.println("新增元素后集合长度:"+list.size());
  15. //判断集合是否为空
  16. System.out.println("集合是否为空:"+list.isEmpty());
  17. //判断集合是否包含指定元素(元素存在)
  18. System.out.println("集合中是否包含元素“hello”:"+list.contains("hello"));
  19. //判断集合是否包含指定元素(元素不存在)
  20. System.out.println("集合中是否包含元素“haha”:"+list.contains("haha"));
  21. //取得集合指定位置的元素
  22. System.out.println("下标为2的元素:"+list.get(2));
  23. //修改指定位置的元素
  24. System.out.println("修改下标为3的元素:");
  25. list.set(3, "lemon");
  26. System.out.println("修改元素后将集合中元素转化为数组并打印"+list.toArray());
  27. for (String string : list) {
  28. System.out.print(" "+string);
  29. }
  30. System.out.println();
  31. //清空集合中元素
  32. System.out.println("清空集合:");
  33. list.clear();
  34. System.out.println("清空后集合是否为空:"+list.isEmpty());
  35. }
  36. }

由上述运行结果我们可以发现List可以存储重复元素。

get()方法是List子接口提供的,根据指定下标返回元素。若我们要对Collection接口实现此操作,则引用该将其转换为对象数组再进行操作。


  1. //利用Collection实现get()方法
  2. public class Test {
  3. public static void main(String[] args) {
  4. //这时候集合中只能存String类型的数据
  5. Collection<String> list = new ArrayList<>();
  6. list.add("hello");
  7. list.add("world");
  8. //添加重复元素
  9. list.add("hello");
  10. list.add("陕科大");
  11. //操作以Object为主,可能需要向下转型,就会出现ClassCastException异常
  12. Object[] object = list.toArray();
  13. System.out.println(Arrays.toString(object));
  14. System.out.println("下标为2的元素:"+object[2]);
  15. }
  16. }

(1)Vector

Vector是jdk1.0提出的,而ArrayList是jdk1.2提出的,Vector相对使用较少。

Vector的使用与ArrayList的使用类似


  1. public class Test {
  2. public static void main(String[] args) {
  3. //这时候集合中只能存String类型的数据
  4. List<String> list = new Vector<>();
  5. list.add("hello");
  6. list.add("world");
  7. //添加重复元素
  8. list.add("hello");
  9. System.out.println(list);
  10. //返回集合中元素的个数
  11. System.out.println("新增元素后集合长度:"+list.size());
  12. //判断集合是否为空
  13. System.out.println("集合是否为空:"+list.isEmpty());
  14. //判断集合是否包含指定元素(元素存在)
  15. System.out.println("集合中是否包含元素“hello”:"+list.contains("hello"));
  16. //判断集合是否包含指定元素(元素不存在)
  17. System.out.println("集合中是否包含元素“haha”:"+list.contains("haha"));
  18. //取得集合指定位置的元素
  19. System.out.println("下标为2的元素:"+list.get(2));
  20. //修改指定位置的元素
  21. System.out.println("修改下标为3的元素:");
  22. list.set(1, "lemon");
  23. System.out.println("修改元素后将集合中元素转化为数组并打印"+list.toArray());
  24. for (String string : list) {
  25. System.out.print(" "+string);
  26. }
  27. System.out.println();
  28. //清空集合中元素
  29. System.out.println("清空集合:");
  30. list.clear();
  31. System.out.println("清空后集合是否为空:"+list.isEmpty());
  32. }
  33. }

ArrayList和Vector的区别:

A. 时间上:Vector是jdk1.0提供的;而ArrayList是jdk1.5提供的。

B. 处理形式:Vector是同步处理,性能较低;而ArrayList是异步处理,性能相对高。

C. 数据安全:Vector是线程安全的;而ArrayList是非线程安全的。

D. 输出形式:Vector支持Iterator、ListIterator、 foreach、Enumeration输出;而ArrayList支持Iterator、ListIterator、foreach输出。

(2)LinkedList

若还是利用子类向父类转型来使用的话,LinkedList的使用和前面两者也没什么区别。

ArrayList和LinkedList的区别:

观察ArrayList的源码,可以发现ArrayList里面存放的是一个数组,如果实例化此对象时传入了数组的大小,则里面保存的数组就会开辟一个定长的数组,但是后续中再进行数据保存,若该长度不够使用则会对数组进行动态扩充。所以我们在使用ArrayList时最好对其设置初始化大小。

LinkedList就是一个纯粹的链表实现,除性能高外与我们编写的链表没有什么区别。

ArrayList封装的是数组,而LinkedList封装的是链表。进行查找时ArrayList的时间复杂度为1,而LinkedList的时间复杂度为n。

3、Set接口

与List接口相比Set:Set中的内容是不允许重复的,且没有对Collection接口再进行方法的扩充。所以Set中没有get()方法。

Set接口中提供与两个常用子类:HashSet(无需存储)和TreeSet(有序存储)。


  1. public class Test{
  2. public static void main(String[] args) {
  3. //Set<Integer> set = new HashSet<>();
  4. Set<Integer> set = new TreeSet<>();
  5. set.add(20);
  6. set.add(6);
  7. set.add(15);
  8. set.add(-3);
  9. set.add(20);
  10. //添加重复元素
  11. System.out.println(set);
  12. }
  13. }

HashSet运行后结果                TreeSet运行后结果

                                      

由此我们可以看出HashSet是对集合进行无需存储,而TreeSet则对集合进行有序存储(采用升序模式进行排列)。

(1)TreeSet中排序的分析

因此我们对TreeSet的排序来进行分析:

由于TreeSet可以进行排序操作,所以我们可以来实现数据的排序处理。此时进行的排序实际是针对对象数组进行的排序处理,而如果要对对象数组进行排序,则对象所在的类要实现Comparable接口并且要覆写compareTo()方法(要利用Comparable接口进行大小关系比较时必须要对所有的属性进行比较操作)。


  1. //自定义类
  2. class Person implements Comparable<Person>{
  3. private String name;
  4. private Integer age;
  5. @Override
  6. public String toString() {
  7. return "Person [name=" + name + ", age=" + age + "]";
  8. }
  9. Person(String name, Integer age) {
  10. super();
  11. this.name = name;
  12. this.age = age;
  13. }
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public Integer getAge() {
  21. return age;
  22. }
  23. public void setAge(Integer age) {
  24. this.age = age;
  25. }
  26. @Override
  27. public int compareTo(Person o) {
  28. if(this.age > o.age) {
  29. return 1;
  30. }else if(this.age < o.age) {
  31. return -1;
  32. }else {
  33. return this.name.compareTo(o.name);
  34. }
  35. }
  36. }
  37. public class Test{
  38. public static void main(String[] args) {
  39. Set<Person> set = new TreeSet<>();
  40. set.add(new Person("lemon",20));
  41. set.add(new Person("demon", 20));
  42. set.add(new Person("lemon",20));
  43. System.out.println(set);
  44. }
  45. }

这样一个一个属性进行比较的操作过于麻烦,所以一般情况下我们都使用HashSet。

(2)重复元素的判断在使用TreeSet子类进行数据保存时。重复元素的判断依靠Comparable接口来实现。但是这并不是全部Set接口判断元素重复的方式,因为如果使用的是HashSet子类,因为其和Comparable没有任何关系,所以它判断重复要依靠Object类的两个方法:

hash码: public native int hashCode();

对象比较:public boolean equals(Object obj);

在Java中进行对象比较的操作有两个步骤:第一步要通过一个对象的唯一编码找到一个对象的信息,当编码匹配之后再进行下一步操作利用equals()方法进行内容比较。


  1. /*
  2. * 标识对象的唯一性
  3. * */
  4. //自定义类
  5. class Person implements Comparable<Person>{
  6. private String name;
  7. private Integer age;
  8. @Override
  9. public String toString() {
  10. return "Person [name=" + name + ", age=" + age + "]";
  11. }
  12. Person(String name, Integer age) {
  13. super();
  14. this.name = name;
  15. this.age = age;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. public Integer getAge() {
  24. return age;
  25. }
  26. public void setAge(Integer age) {
  27. this.age = age;
  28. }
  29. public int compareTo(Person o) {
  30. if(this.age > o.age) {
  31. return 1;
  32. }else if(this.age < o.age) {
  33. return -1;
  34. }else {
  35. return this.name.compareTo(o.name);
  36. }
  37. }
  38. @Override
  39. public int hashCode() {
  40. return Objects.hash(name,age);
  41. }
  42. @Override
  43. public boolean equals(Object obj) {
  44. if(this == obj) {
  45. return true;
  46. }
  47. if(obj == null|| getClass()!=obj.getClass()) {
  48. return false;
  49. }
  50. Person person = (Person) obj;
  51. return Objects.equals(name,person.name)
  52. && Objects.equals(age,person.age);
  53. }
  54. }
  55. public class Test{
  56. public static void main(String[] args) {
  57. Set<Person> set = new HashSet<>();
  58. set.add(new Person("lemon",20));
  59. set.add(new Person("lemon",20));
  60. set.add(new Person("demon", 18));
  61. System.out.println(set);
  62. }
  63. }

不覆写hashCode()和equals()方法或只覆写一个运行结果:

两个方法覆写后运行结果:

所以想要标识出对象的唯一性,则必须覆写hashCode()和equals()两个方法。

如果两个对象的hashCode()相同,equals()不同;或两个对象的equals()相同,而hashCode()不同时,这两个对象都是不能消除。而只有当两个对象的hashCode()和equals()都相同时,这两个对象才能判定为同一对象,即相同。

所以在保存自定义类信息时,建议使用List接口。而保存系统类信息时,建议使用Set接口。

集合类——Collection、List、Set接口的更多相关文章

  1. Java中的集合(五)继承Collection的List接口

    Java中的集合(五)继承Collection的List接口 一.List接口简介 List是有序的Collection的,此接口能够精确的控制每个元素插入的位置.用户能够根据索引(元素在List接口 ...

  2. ios 对象的集合类(collection classes)

    当你着手为你的应用编写代码的时候,你会发现有许多可供使用的Objective-C的框架类,其中尤其重要的就是基础框架类,它为平台所有的应用提供基础服务.基础框架类中包括了表示字符串和数字等基本数据类型 ...

  3. Java容器深入浅出之Collection与Iterator接口

    Java中用于保存对象的容器,除了数组,就是Collection和Map接口下的容器实现类了,包括用于迭代容器中对象的Iterator接口,构成了Java数据结构主体的集合体系.其中包括: 1. Co ...

  4. Java中的集合(六)继承Collection的Set接口

    Java中的集合(六)继承Collection的Set接口 一.Set接口的简介 Set接口和List接口都是继承自Collection接口,它与Collection接口中功能基本一致,并没有对Col ...

  5. Java中的集合(三)继承Collection的Queue接口

    Java中的集合(三)继承Collection的Queue接口 一.Queue介绍 Queue接口继承自Collection接口,是Java中定义的一种队列数据结构,元素是有序的(按插入顺序排序),先 ...

  6. 集合类 collection接口 ArrayList

    数组: 存储同一种数据类型的集合容器.数组的特点:1. 只能存储同一种数据类型的数据.2. 一旦初始化,长度固定. 3. 数组中的元素与元素之间的内存地址是连续的. : Object类型的数组可以存储 ...

  7. 集合类 collection接口 Set

    Collection接口的另外一种实现为Set集合,主要有两种实现方式一种为HashSet另一种为TreeSet,两种实现都依赖与对应的Map实现类. 代码如下: public HashSet() { ...

  8. 集合类(Collection和Map接口)简介

    集合分为Collection和Map,详细分类如下图所示: 以下是测试验证代码: //HashSet,无序(存取不一致).去重 Set set_H = new HashSet(); set_H.add ...

  9. 集合类 collection接口 LinkedList

    LinkedList 是另外一种重要的数据结构形式, 底层是使用了双向链表数据结构, 特点: 查询速度慢,增删快. 继承关系如下: 可以发现,LinkedList同时实现了Quene和Deque接口. ...

随机推荐

  1. Docker 18.03导入导出

    docker中分容器和镜像,简单可以理解为容器是运行中的实例,镜像是运行实例所需的静态文件. 导入导出既可以对容器做操作,也可以对镜像做操作.区别在于镜像可以随时导出,容器必须要停止之后才可以导出,否 ...

  2. Oracle创建表、删除表、修改表、字段增删改 语句总结

    创建表: create table 表名 ( 字段名1 字段类型 默认值 是否为空 , 字段名2 字段类型 默认值 是否为空, 字段名3 字段类型 默认值 是否为空, ...... ); 创建一个us ...

  3. openssh 8.2 升级 8.3

    openssh 8.2 存在安全漏洞,升级为 openssh 8.3 需要安装的包:openssh-8.3p1.tar.gz.zlib-1.2.11.tar.gz.openssl-1.1.1g.tar ...

  4. .net core 和 WPF 开发升讯威在线客服系统:把 .Net Framework 打包进安装程序

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程. 系列文章目录: https://blog.shengxunwei.com/Home/Post/44a3 ...

  5. 【微服务落地】服务间通信方式: gRPC的入门

    gRPC是什么 官方介绍: https://grpc.io/docs/what-is-grpc/introduction/ "A high-performance, open-source ...

  6. APP自动化环境搭建之appium工具介绍(二)

    1.下载解压android-sdk-windows-appium //配置环境: ANDROID_HOME:D:\android-sdk-windows-appium path:...;%ANDROI ...

  7. 旧电脑做服务器--第一篇 sql server 服务器搭建

    背景:旧电脑为2015年的老电脑,联系G50系列,目前键盘鼠标操作都有问题,键盘按键和鼠标左键莫名奇妙变成右击,屏幕显示也是大颗粒.但是配置还可以,16GB内存+256GB三星固态硬盘.所以想搭建作为 ...

  8. 【Mysql】表锁 行锁 记录锁 间隙锁

    Mysql中的锁 基于锁的属性分类:共享锁.排他锁. 基于锁的状态分类:意向共享锁.意向排它锁 根据锁的粒度分类:全局锁.页锁.表级锁.行锁(记录锁.间隙锁.和临键锁),实际上的锁就这些,上面两种分类 ...

  9. PAT A1107——并查集

     Social Clusters When register on a social network, you are always asked to specify your hobbies in ...

  10. 【JavaSE】格式化输出

    Java格式化输出 2019-07-06  11:35:55  by冲冲 1. 输出字符串 %s 1 /*** 输出字符串 ***/ 2 // %s表示输出字符串,也就是将后面的字符串替换模式中的%s ...