集合框架

简介: 集合框架简介集合的由来   数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少 定义:  java提供了一种可以存数一组数据的数据结构,其提供了丰富的方法,在实际开发中往往比数组使用的广泛。

集合框架

简介

集合的由来
  数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少

定义:

  java提供了一种可以存数一组数据的数据结构,其提供了丰富的方法,在实际开发中往往比数组使用的广泛。这种数据结构成为集合:Collection。

  Collection是一个接口,其定义了集合的相关功能方法。

数组和集合的区别

  • 区别1 :
    • 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
    • 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
  • 区别2:
    • 数组长度是固定的,不能自动增长
    • 集合的长度的是可变的,可以根据元素的增加而增长

数组和集合什么时候用

  • 如果元素个数是固定的推荐用数组
  • 如果元素个数不是固定的推荐用集合

集合框架图

这里写图片描述

Collection (集合的最大接口)继承关系

  ——List 可以存放重复的内容
  ——Set  不能存放重复的内容,所以的重复内容靠hashCode()和equals()两个方法区分
  ——Queue  队列接口
  ——SortedSet  可以对集合中的数据进行排序

关于list,set,map的我的博客链接java集合(list,set,map)

Collection定义了集合框架的共性功能。

Collection接口常见的方法

(1)单元素添加、删除操作。

方法 描述
boolean add(Object o) 将对象添加给集合。
boolean remove(Object o) 如果集合中有与o相匹配的对象,则删除对象o。

(2)查询操作。

方法 描述
int size() 返回当前集合中元素的数量。
boolean isEmpty() 判断结合中是否有任何元素。
boolean contains(Object o) 查找集合中是否含有元素o。
Iterator iterator() 返回一个迭代器,用来访问集合中的各个元素。

(3)组操作:作用于元素或整个结合。

方法 描述
boolean containsAll(Collection c) 查找集合中是否含有集合c中的所有元素。
boolean addAll(Collectiion c) 将集合c中的所有元素添加给该集合。
void clear() 删除集合中所有的元素。
void removeAll(Collection c) 从集合中删除集合c中的所有元素。
void retainAll(Collection c) 从集合中删除集合c中不包含的元素。

(4)Collection转换为Object数组。

方法 描述
Object[] toArray() 返回一个内含集合所有元素的数组。
Object[] toArray(Object[] a) 返回一个内含集合所有元素的数组。运行期返回的数组和参数a的类型相同。

注:集合中存储的都是对象的引用(地址)

Iterator 迭代器

Collection提供了一个遍历集合的通用方式,迭代器(Iterator)。
获取迭代器的方式是使用Collection定义的方法:

Iterator iterator():迭代器Iterator是一个接口,集合在覆盖Collection的iterator()方法时提供了迭代器的实现。Iterator提供了统一的遍历集合元素的方式。

迭代器原理

迭代器原理:迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二:
  第一规定了整个集合体系的遍历方式都是hasNext()和next()方法;
  第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可

hasNext与next方法

迭代器用于遍历集合的两个主要方法:

  • boolean hasNext():判断集合是否还有元素可以遍历。

  • E next():返回迭代的下一个元素

    遍历集合应遵循“先问后取”的方式,也就是说,应当在确定hasNext()方法的返回值为true的情况下再通过next()方法取元素。

    由此可以看出,使用迭代器遍历集合是通过boolean值驱动的,所以它更适合使用while循环来遍历。

    Collection<String> c = new HashSet<String>();
    c.add("java");        
    c.add("cpp");        
    c.add("php");
    c.add("c#");        
    c.add("objective-c");
    Iterator<String> it = c.iterator();
    while (it.hasNext()) {
        String str = it.next();
        System.out.println(str);
    } 

remove方法

  迭代器还提供了一个方法:

  void remove()该方法用于删除迭代器当次从集合中获取的元素。若我们在迭代过程中想删除集合元素时,我们就需要通过该方法来进行。这里需要注意,在使用迭代器遍历集合时是不能通过集合自身提供的remove方法删除元素的,否则迭代器在迭代时会抛出异常。

    Collection<String> c = new HashSet<String>();
    c.add("java");        
    c.add("cpp");        
    c.add("php");
    c.add("c#");        
    c.add("objective-c"); 
    System.out.println(c); // [cpp, php, c#, java, objective-c] 
    Iterator<String> it = c.iterator();
    while (it.hasNext()) {
        String str = it.next();
        if (str.indexOf("c") != -1) {
            it.remove();
        } 
    } 
    System.out.println(c); // [php, java]  

增强for循环

Java5.0之后推出了一个新的特性,增强for循环,也称为新循环。该循环不通用于传统循环的工作,其只用于便利集合或数组。 语法:

    for(元素类型 e : 集合或数组){
        循环体 
    }

  新循环并非新的语法,而是在编译过程中,编译器会将新循环转换为迭代器模式。所以新循环本质上是迭代器。
例如:

    Collection<String> c = new HashSet<String>();
    c.add("java");
    c.add("cpp");
    c.add("php");
    c.add("c#");
    c.add("objective-c");
    for (String str : c) {
        System.out.print(str.toUpperCase() + " ");
    } 
    // CPP PHP C# JAVA OBJECTIVE-C

泛型机制

泛型在集合中的应用

  泛型是Java SE 5.0引入的特性,泛型的本质是参数化类型。在类、接口和方法的定义过程中,所操作的数据类型被传入的参数指定。

  Java泛型机制广泛的应用在集合框架中。所有的集合类型都带有泛型参数,这样在创建集合时可以指定放入集合中的对象类型。Java编译器可以据此进行类型检查,这样可以减少代码在运行时出现错误的可能性。

我们来举个例子,比如ArrayList,其在定义时是这样的:

    public class ArrayList<E> {
        … … …                
        public boolean add(E e) {…};
        public E get(int index) {…};
    } 

由此我们可以看出,再声明ArrayList时,类名的右侧有一个。”<>”表示泛型,而其中可以使用数字字母下划线(数字不能的第一个字符)来表示泛型的名字。(通常我们使用一个大写字母来表示,当然这个不是规定。)这时,在类中声明的方法的参数,返回值类型可以被定义为泛型。这样在创建对象时可以将类型作为参数传递,此时,类定义所有的E将被替换成传入的参数。
例如:

    ArrayList<String> list = new ArrayList<String>();//泛型E在这里被指定为String类型
    list.add("One");//那么add方法的参数就被替换为String类型
    list.add(100);//这里就会出现编译错误,因为这里的参数应为String类型。

集合工具类

 Collections:集合框架的工具类。里面定义的都是静态方法。

  Collections和Collection有什么区别?
    Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
      它有两个常用的子接口,
      List:对元素都有定义索引。有序的。可以重复元素。
      Set:不可以重复元素。无序。

    Collections是集合框架中的一个工具类。该类中的方法都是静态的。
      提供的方法中有可以对list集合进行排序,二分查找等方法。
      通常常用的集合都是线程不安全的。因为要提高效率。
      如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

常用的方法

排序操作(主要针对List接口相关)

方法 描述
reverse(List list) 反转指定List集合中元素的顺序
shuffle(List list) 对List中的元素进行随机排序(洗牌)
sort(List list) 对List里的元素根据自然升序排序
sort(List list, Comparator c) 自定义比较器进行排序
swap(List list, int i, int j) 将指定List集合中i处元素和j出元素进行交换

rotate(List list, int distance)|将所有元素向右移位指定长度,如果distance等于size那么结果不变|

例子

    public void testSort() {
        System.out.println("原始顺序:" + list);

        Collections.reverse(list);
        System.out.println("reverse后顺序:" + list);

        Collections.shuffle(list);
        System.out.println("shuffle后顺序:" + list);

        Collections.swap(list, 1, 3);
        System.out.println("swap后顺序:" + list);

        Collections.sort(list);
        System.out.println("sort后顺序:" + list);

        Collections.rotate(list, 1);
        System.out.println("rotate后顺序:" + list);
    }

输出

原始顺序:[b张三, d孙六, a李四, e钱七, c赵五]
reverse后顺序:[c赵五, e钱七, a李四, d孙六, b张三]
shuffle后顺序:[b张三, c赵五, d孙六, e钱七, a李四]
swap后顺序:[b张三, e钱七, d孙六, c赵五, a李四]
sort后顺序:[a李四, b张三, c赵五, d孙六, e钱七]
rotate后顺序:[e钱七, a李四, b张三, c赵五, d孙六]

查找和替换(主要针对Collection接口相关)

方法 描述
binarySearch(List list, Object key) 使用二分搜索法,以获得指定对象在List中的索引,前提是集合已经排序
max(Collection coll) 返回最大元素
max(Collection coll, Comparator comp) 根据自定义比较器,返回最大元素
min(Collection coll) 返回最小元素
min(Collection coll, Comparator comp) 根据自定义比较器,返回最小元素
fill(List list, Object obj) 使用指定对象填充
frequency(Collection Object o) 返回指定集合中指定对象出现的次数
replaceAll(List list, Object old, Object new) 替换

例子

        public void testSearch() {
        System.out.println("给定的list:" + list);
        System.out.println("max:" + Collections.max(list));
        System.out.println("min:" + Collections.min(list));
        System.out.println("frequency:" + Collections.frequency(list, "a李四"));
        Collections.replaceAll(list, "a李四", "aa李四");
        System.out.println("replaceAll之后:" + list);

        // 如果binarySearch的对象没有排序的话,搜索结果是不确定的
        System.out.println("binarySearch在sort之前:" + Collections.binarySearch(list, "c赵五"));
        Collections.sort(list);
        // sort之后,结果出来了
        System.out.println("binarySearch在sort之后:" + Collections.binarySearch(list, "c赵五"));

        Collections.fill(list, "A");
        System.out.println("fill:" + list);
    }

输出

给定的list:[b张三, d孙六, a李四, e钱七, c赵五]
max:e钱七
min:a李四
frequency:1
replaceAll之后:[b张三, d孙六, aa李四, e钱七, c赵五]
binarySearch在sort之前:-4
binarySearch在sort之后:2
fill:[A, A, A, A, A]

同步控制

  Collections工具类中提供了多个synchronizedXxx方法,该方法返回指定集合对象对应的同步对象,从而解决多线程并发访问集合时线程的安全问题。HashSet、ArrayList、HashMap都是线程不安全的,如果需要考虑同步,则使用这些方法。这些方法主要有:synchronizedSet、synchronizedSortedSet、synchronizedList、synchronizedMap、synchronizedSortedMap。

  特别需要指出的是,在使用迭代方法遍历集合时需要手工同步返回的集合。

Map m = Collections.synchronizedMap(new HashMap());
      ...
  Set s = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized (m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
    }

总结

 List:add/remove/get/set。

    1,ArrayList:其实就是数组,容量一大,频繁增删就是噩梦,适合随机查找;

    2,LinkedList:增加了push/[pop|remove|pull],其实都是removeFirst;

    3,Vector:历史遗留产物,同步版的ArrayList,代码和ArrayList太像;

    4,Stack:继承自Vector。Java里其实没有纯粹的Stack,可以自己实现,用组合的方式,封装一下LinkedList即可;

    5,Queue:本来是单独的一类,不过在SUN的JDK里就是用LinkedList来提供这个功能的,主要方法是offer/pull/peek,因此归到这里呢。

  Set:add/remove。可以用迭代器或者转换成list。

    1,HashSet:内部采用HashMap实现的;

    2,LinkedHashSet:采用LinkedHashMap实现;

    3,TreeSet:TreeMap。

  Map:put/get/remove。

    1,HashMap/HashTable:散列表,和ArrayList一样采用数组实现,超过初始容量会对性能有损耗;

    2,LinkedHashMap:继承自HashMap,但通过重写嵌套类HashMap.Entry实现了链表结构,同样有容量的问题;

    3,Properties:是继承的HashTable。

    顺便说一下Arrays.asList,这个方法的实现依赖一个嵌套类,这个嵌套类也叫ArrayList!

相关文章
|
8月前
|
XML Java 数据库连接
优雅的参数校验,告别冗余if-else
本文介绍了在 Java Spring Boot 开发中如何使用 JSR 303 和 Hibernate Validator 进行参数校验,以避免冗余的if-else判断。文章涵盖了基本注解的使用、全局异常处理、分组校验、嵌套对象校验、快速失败配置以及自定义校验规则等实用技巧。
269 10
优雅的参数校验,告别冗余if-else
|
存储 缓存 关系型数据库
MariaDB 和 GreatSQL 性能差异背后的真相
【10月更文挑战第22天】本文介绍了 MariaDB 和 GreatSQL 两款数据库系统的背景、性能差异因素及实际应用场景。MariaDB 是 MySQL 的分支,具有良好的社区支持和丰富的插件生态系统;GreatSQL 是国产的 MySQL 兼容数据库,专注于企业级应用场景。文章详细对比了两者的存储引擎优化、查询优化器差异、缓存机制和并发处理能力,并分析了它们在 OLTP 和 OLAP 场景中的性能表现。
549 3
|
存储 运维 Kubernetes
容器镜像的构建与管理实践
在云原生时代,容器技术已成为现代软件开发和运维不可或缺的一部分。本文将深入探讨容器镜像的构建流程、管理策略以及安全性考量,旨在为读者提供一套系统化的容器镜像管理方案。我们将从实际案例出发,分析容器镜像构建的最佳实践,同时指出常见的陷阱与误区。此外,文章还将介绍如何有效利用现有的工具和平台来提升容器镜像的安全性和管理效率,确保在快速迭代的开发周期中,能够维护镜像的一致性和可靠性。
399 27
|
机器学习/深度学习 自然语言处理 并行计算
淘宝搜索中的深度语义模型:从理论到实践
淘宝搜索系统通过引入深度语义模型,极大地提升了搜索质量和用户体验。这些模型不仅能够准确理解用户的需求,还能够智能地匹配和推荐商品,为用户提供了一个更加便捷、个性化的购物环境。随着技术的不断发展和完善,淘宝搜索将会变得更加智能和高效。
|
JavaScript Java 测试技术
基于微信小程序的医院挂号系统的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的医院挂号系统的设计与实现(源码+lw+部署文档+讲解等)
208 1
|
自然语言处理 安全 区块链
Chatchat:为语言链而生的新时代
Chatchat:为语言链而生的新时代
603 9
|
机器学习/深度学习 数据可视化 算法
PACNet & CellNet(代码开源)|bulk数据作细胞分类,评估细胞命运性能的一大利器
PACNet和CellNet都是强大的工具,分别用于研究细胞命运工程和细胞类型保真度,它们在细胞类型分类和网络分析方面有所不同,可以根据研究需求选择合适的工具。
418 1
|
人工智能 前端开发 算法
未来人工智能技术在前端开发中的应用与挑战
随着人工智能技术的迅猛发展,前端开发领域也开始探索其在用户体验、性能优化等方面的应用。本文将探讨未来人工智能技术在前端开发中的潜在应用和可能面临的挑战。
|
存储 机器学习/深度学习 Unix
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
|
小程序 前端开发 开发工具
微信小程序云开发|基于微信小程序实现房产中介平台系统(一)
微信小程序云开发|基于微信小程序实现房产中介平台系统
321 0