java中单列集合的根接口是_快速带你梳理Java单列集合之Collection

1. 集合概述

由于我们开发过程中,难以避免不去操作数据,操作对象就有可能对数据进行存储,存储数据的方式多种多样,之前我们都是将数据存储在数组中,但数组的特点是长度固定不可改变的,这样就不适合用于存储变化(个数的变化)的数据。因此,Java提供一种容器用于存储数据,这个容器就叫做集合。

2. 集合和数组的区别

数组:

长度固定可以存储基本数据类型,也可以存储引用数据类型存储的数据类型必须要一致(比如说创建一个int类型的数组,它就只能存整数,不能存double或者String类型等)集合:

长度可变只能存储引用数据类型可以存储不同类型的对象。(可以存int、String、double等)

3. 集合的体系:

0950a00d35820350e1dd33c85ff3d860.png

4.下面看一下各成员特点

|- - List:有序(序指的是存和取得顺序一致,怎么样存就怎么样取),元素可以重复|- - - - - - - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全,效率高|- - - - - - - Vector: 底层数据结构是数组,查询快,增删慢,线程安全,效率低|- - - - - - - LinkedList: 底层数据结构是链表,查询慢,增删快,线程不安全,效率高

|- - Set:无序,元素不可以重复|- - - - - - - HashSet: 底层数据结构是哈希表,线程不安全,效率高|- - - - - - - TreeSet: 底层数据结构是二叉树,线程不安全,效率高

5. Collection接口中的常用方法

2aa911492c620168ebf36799a05ceaff.png

注:Collection是一个根接口,继承它的子类或者子接口都能使用它的方法

6. List集合特有的方法

5df49477bdd2f3b8604fa5647525f927.png

7. ArrayList

ArrayList是List接口下的一个实现类之一,也是最常用的一个集合,由于它的底层是数组结构实现的,因此可以看成是一个长度可变的数组,下面介绍关于ArrayList的常见使用

7.1 集合的遍历

7.1.1.通过集合转数组,然后再对数组进行遍历

Collection c = new ArrayList(); c.add("abc"); c.add("abcd"); c.add("abcde"); Object[] array = c.toArray(); //将集合转为数组 for(int i=0; i

7.1.2.通过get()和size()方法结合(仅仅适用于Collection的子接口List接口)

//定义一个ArrayList集合 ArrayList arrayList = new ArrayList(); arrayList.add(10); arrayList.add(50); arrayList.add("你好"); arrayList.add(8); for (int i = 0; i < arrayList.size(); i++) { Object obj = arrayList.get(i); //根据索引获取值,在此返回的是Object数据类型 System.out.print(obj + " "); }

7.1.3.通过迭代器实现(适用于所有集合) (下面将会介绍)

//定义一个ArrayList集合 ArrayList arrayList = new ArrayList(); arrayList.add(10); arrayList.add(50); arrayList.add("你好"); arrayList.add(8); //第一步:创建迭代器对象 Iterator iterator = arrayList.iterator(); //第二步:通过hasNext()方法判断迭代器中是否有元素 while (iterator.hasNext()) { //第三步:通过next()方法获取元素 Object object = iterator.next(); System.out.print(object + ""); }}

7.1.4.通过增强for循环遍历(适用于所有集合和数组) (推荐使用)注意:增强for只能操作集合和数组定义格式:for(数据类型 临时变量名 : 集合或者数组){

}例如定义了一个集合ArrayList list = new ArrayList();此处的集合如不指定数据类型,默认为Object类型,则它的增强for格式就为:for(Object obj:list) {}

//定义一个ArrayList集合 ArrayList arrayList = new ArrayList(); arrayList.add(10); arrayList.add(50); arrayList.add("你好"); arrayList.add(8); //增强for进行遍历 for (Object object : arrayList) { System.out.print(object + " "); }

7.2 迭代器

7.2.1 何为迭代器迭代器是从集合中取出元素的一种标准方式,我们取出任何集合中的元素都可以按照这个标准来获取,主要遍历Collection集合中的元素。迭代是取出集合中元素的一种方式7.2.2 原理因为多种集合的数据结构不同,所以存储方式不同,因此取出方式也不同。这个时候,我们就把判断和获取功能定义在了一个接口中,将来,遍历哪种集合的时候,只要该集合内部实现这个接口即可(由于集合内部已经实现了该接口,因此直接使用即可,无需我们手动实现 )7.2.3 使用方式通过集合对象调用iterator()方法便可获得一个且迭代器对象Iterator,然后再通过hasNext()方法判断是否含有元素,最后通过next()方法获取集合中的元素。(使用示例见上文7.1集合遍历中的第三种方法)7.2.4 常见问题在我们对集合进行遍历的时候,有时候可能会对集合进行删除或者增加元素。但当我们使用Iterator对集合进行遍历的同时进行增删操作时,会出现一个异常,那就是并发修改异常 ConcurrentModificationException。 但要是我们硬是要在迭代的时候对元素进行增删操作的时候该肿么办呢?这时就有一个办法解决啦!这个办法就是通过集合对象获取Iterator的子接口ListIterator (例如:ListIterator iterator = arrayList.listIterator(); )7.2.5 Iterator 和 ListIterator的区别1、Iterator是ListIterator的父接口2、Iterator是Collection集合的公共的取出容器中元素的方式,对于List,Set都通用。而ListIterator是List集合的特有的取出元素的方式3、Iterator中只具备hasNext(),next(),remove()方法,可以删除被遍历到的元素ListIterator中具备对遍历到的元素进行增(add)删(remove)改(set)查(next)的方法,可以对元素逆向遍历previouse相对于next,hasPreviouse相对于hasNext(用的很少)7.2.6 Iterator 和 ListIterator的成员方法

238008621a76be26b9cc2bc9cb3bef72.png

8. LinkedList

LinkedList底层实现是链式结构,它的特点是增加删除元素快,查询元素慢。就像人们手牵手连在一起排成一条队列,每个人就可以看做一个元素,当有一个人想进入或者退出队列的时候,只是旁边两人断开手就行了,要是想查询某人处于什么位置,只能从开头或者默认一个一个地查询下去,这样效率就大大下降了。8.1 特有的方法

6fec9872b9985855074634a470ffedfa.png

9. 泛型

9.1 何为泛型泛型是一种把明确类型的工作放在了创建对象或者调用方法时候才去明确的特殊的类型,泛型就相当于一个预定义类型9.2 好处

把系统运行期间的异常提前到了编译期间,提高了安全性优化了程序设计,不需要再做强壮了9.3 缺点泛型只能传入引用类型,不能传入基本类型,如需要传入基本类型只能传入基本类型对应的包装类类型包装类表如下:

b890f6bcebc41a0f5b9251642fb3ba42.png

9.4 泛型的使用泛型可以定义在类中,方法中和接口中。下面介绍在创建对象时使用泛型和不使用泛型的区别。不使用泛型时:

//定义一个ArrayList集合,没有指定泛型,默认为Object类型 ArrayList arrayList = new ArrayList(); arrayList.add("元素1"); arrayList.add("元素2"); arrayList.add("元素3"); for (int i = 0; i < arrayList.size(); i++) { //由于ArrayList默认为Object类型,因此在不加泛型的时候获取元素需要强转 String string = (String) arrayList.get(i); System.out.print(string + " "); }

使用泛型:

//定义一个ArrayList集合,指定泛型为String类型 ArrayList arrayList = new ArrayList(); arrayList.add("元素1"); arrayList.add("元素2"); arrayList.add("元素3"); //arrayList.add(2); 这里如果添加非String类型,会报错,因为已经指定泛型,从而将运行期间的异常提前到了编译期间 for (int i = 0; i < arrayList.size(); i++) { //由于在创建集合对象时已经给定泛型,因此在此不需要强转 String string = arrayList.get(i); System.out.print(string + " "); }

10. ArrayList练习

需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)

/** * 思路:想要对集合中的元素进去重,可以创建一个新的集合, 然后再遍历的时候判断新集合是否包含某个元素。 如果有了就不添加,否则就添加到新集合里面,最终得到的新集合就是没有重复元素的集合。 */

11. HashSet集合

HashSet集合存储的元素不会重复,并且存储顺序是不一致的。那么HashSet集合在添加元素时是如何保证元素不会重复添加呢?其实它是通过两个方法来进行判断的。11.1 保证不重复添加元素

hashCode()方法:首先通过调用对象的hashCode() 方法,返回一个int型的数据,这个数据就是哈希值。当存储两个元素时,会判断这两个元素的哈希值是否相同,如果不相同,就添加到集合中;否则会进行调用equals()方法equals()方法:当两个元素的元素哈希值相等时,会调用此方法来判断两者的内容是否相同。不同则添加,相同就不添加到集合中注意: 如果两个元素的哈希值不同,就不再需要调用equals方法了。

public class Demo { public static void main(String[] args) { //1.创建一个HashSet集合,并指定为String泛型 HashSet hashSet = new HashSet<>(); //往集合中添加元素 hashSet.add("aa"); hashSet.add("bb"); hashSet.add("aa"); //添加重复元素 hashSet.add("cc"); //获取hashSet的迭代器对象 Iterator iterator = hashSet.iterator(); //对元素进行遍历 while (iterator.hasNext()) { String string = iterator.next(); System.out.print(string + " "); //输出:aa bb cc } }}

11.2 HashSet主要方法通过API可以看出HashSet的主要方法有:

399ae3e6f8ff92bb40f9ac7a9eefe3b8.png

11.3 HashSet存储自定义对象

需求:往HashSet集合中存储Person对象,如果姓名和年龄相同,视为同一个人。首先定义一个Person实体类

// get/set方法省略

然后再创建一个集合存储元素,并遍历

publicclassHashSetTest{publicstaticvoidmain(String[]args){//创建一个集合,并只能存储Person对象HashSeths=newHashSet<>();//往集合中添加了6个元素,有重复hs.add(newPerson("张三",23));hs.add(newPerson("李四",24));hs.add(newPerson("张三",23));hs.add(newPerson("王五",25));hs.add(newPerson("周六",26));hs.add(newPerson("李四",24));//获取迭代器对象对集合进行遍历Iteratoriterator=hs.iterator();while(iterator.hasNext()){Personperson=iterator.next();System.out.println("姓名:"+person.getName()+",年龄:"+person.getAge());}}/* 输出: 姓名:周六,年龄:26 姓名:张三,年龄:23 姓名:李四,年龄:24 姓名:王五,年龄:25 */}

小结:如果想实现HashSet集合存储不重复自定义对象,那么让自定义对象重写hashCode()方法和equals()方法即可。

12. TreeSet集合

TreeSet集合存储元素也是不重复的,它的原理是底层使用二叉树(也可称为红黑树)结构,根据树的节点进行存储和取出。那么何为二叉树结构呢?

将TreeSet集合中存储的第一个元素作为根节点,再进行添加元素的时候,如果比根节点小,就排在根节点的左边,否则就在根节点的右边,相同就不进行任何操作。以此不断进行比较(小的往左,大的往右)下面是二叉树的一张图,有助于理解(图片源于网络,侵删 )

c7db78845de23be4c72f3c0d6324c271.png

12.1 TreeSet常用的方法

d374018582a0f48432c261503d43436d.png

12.2 TreeSet对对象进行排序TreeSet对元素支持自然排序和自定义排序两种排序方式,下面介绍自定义对象排序的两种方式需求:对一个Person对象实现按年龄从大到小排序

方式一: 自定义的对象类实现Comparable接口,重写compareTo()方法自定义对象类:

//get/set方法省略

测试类:

publicclassTreeSetTest{publicstaticvoidmain(String[]args){//创建一个TreeSet集合TreeSetts=newTreeSet<>();ts.add(newPerson("张三",23));ts.add(newPerson("周六",26));ts.add(newPerson("王五",24));ts.add(newPerson("李四",24));//获取迭代器对象Iteratoriterator=ts.iterator();while(iterator.hasNext()){Personperson=iterator.next();System.out.println("姓名:"+person.getName()+",年龄:"+person.getAge());}}/* 输出: 姓名:张三,年龄:23 姓名:王五,年龄:24 姓名:李四,年龄:24 姓名:周六,年龄:26 */}

方式二: 在创建TreeSet集合的时候传入一个比较器(Comparator的子类对象),在比较器中对自定义对象定义排序规则自定义对象类(没有实现Comparable接口)

//get/set方法省略

测试类:

publicclassTreeSetTest{publicstaticvoidmain(String[]args){//创建一个TreeSet集合,并传入一个比较器Comparator,并指定泛型TreeSetts=newTreeSet<>(newComparator(){@Overridepublicintcompare(Persono1,Persono2){//判断年龄是否相等intnum=o1.getAge()-o2.getAge();//按年龄升序排序//int num = o2.getAge() - o1.getAge(); //按年龄降序排序returnnum==0?1:num;}});//往集合中添加数据ts.add(newPerson("张三",23));ts.add(newPerson("周六",26));ts.add(newPerson("王五",24));ts.add(newPerson("李四",24));//获取迭代器对象Iteratoriterator=ts.iterator();while(iterator.hasNext()){Personperson=iterator.next();System.out.println("姓名:"+person.getName()+",年龄:"+person.getAge());}}/* 输出: 姓名:张三,年龄:23 姓名:王五,年龄:24 姓名:李四,年龄:24 姓名:周六,年龄:26 */}

小结:在TreeSet中使存储的自定义对象实现排序。一:在自定义对象类中实现Comparable接口,并重写它的compareTo()方法二:在创建TreeSet集合的时候,传入一个比较器Comparator,并重写它的compare()方法注意:基本数据类型和引用数据类型进行比较的时候是不一样的,同时两者在比较之后得到的结果都是一个int类型的数据,当这个数据等于0的时候,说明比较结果相同,可以用三元运算符返回1(1代表返回对象本身,如不返回1,TreeSet会认为集合已经包含该元素,就不会添加该元素了)

(基本数据类型)升序: this.age - p.age降序: p.age - this.age(引用数据类型)升序:this.name.CompareTo(o.name);降序:o.name.CompareTo(this.name);

完结

如果这篇文章能够对您有所帮助,将是我最大的荣幸,同时文章如有笔误也欢迎指出,共同学习、进步!如需获取更多干货可关注公众号!

公众号名称:【菜鸟码农的日常】

公众号ID:【cnmndrc】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值