集合的框架(之一)

集合的含义:

集合是一个可变的容器,可以随时向集合中添加元素,也可以随时从集合中删除元素。另外,集合还提供了若干个用来操作集合中数据的方法。集合里的数据,我们称之为元素(elements);集合只能用来存储引用类型的数据不能存储八大基本数据类型的数据

泛型

Java SE 5.0 以后,可以使用新特性”泛型”,用来指定要存放在集合中的对象类型。避免了强制转换的麻烦。

public class Person<T> {private T idCard;public Person(T idCard) {this.idCard = idCard;}public static void main(String[] args) {Person person = new Person<String>("1001");}
/*** 当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名*/
Class Student extends Person<Integer>{public Student(Integer idcard){super(idcard);
}class Teacher<E> extends Person<E>{public Teacher(E idcard){super (idcard);
}class Persident extends Person{public Presidert(Object idCard){super (idcard);
}
}
}}}
泛型接口

Public interface MyComparable<T,M>{public int mycompare(T o1, M o2);public static void main(String[] args) {Employee[] employees = new Employee[3];employees[0] = new Employee("John Doe", 23);employees[1] = new Employee("Bane Doe", 33);employees[2] = new Employee("Yane Doe", 18);
Comparator c = new Comparator<Employee>(){
public int compara(Employee o1 ,Employee o2){return o1.mycompare(o1,o2);
}
};
Arrays.sort(employees,c);
System.out.println(Arrays.toString(employees));
}//子类实现接口:   通常子类要给泛型接口的泛型参数赋值具体类型名class Employee implements MyComparable<Employee, Employee> {String name;int age;public Employee(String name ,int age){this.name = name;this.age = age;};//在我们自己定义的方法,来实现比较规则public int mycompare(Employee o1, Employee o2) {return o2.age - o1.age;}@Overridepublic String toString(){return name + " " + age;}}
泛型方法:泛型应用在方法上, 位置位于返回值类型的前面
案例演示:定义一个工具类,用于比较两个对象长得是否一样。
public class MyUtil{public static  <T> boolean equals(T t1,T t2){return t1.equals(t2);
}
public class MyUtil{//工具类public static <T> boolean equals(T t1,T t2){return t1.equals(t2);}public static void main(String[] args) {Cat c1 = new Cat("十八八");Cat c2 = new Cat("十八八");//泛型方法在调用期间,不需要指定具体类型,只需要传入具体对象, 编译器会自动推断对象的类型//泛型方法调用期间,并没有给泛型参数赋值。下面的案例是c1给t1,c2给t2赋值,没有给T赋值。boolean equals = MyUtil.equals(c1, c2);System.out.println(equals);}
}
class Cat{//自定义的类都应该重写equals(),toString()等方法String name;public Cat(String name){this.name = name;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Cat cat = (Cat) o;return Objects.equals(name, cat.name);}@Overridepublic int hashCode() {return Objects.hashCode(name);}
}}
泛型通配符: ?   用于表名不关心调用时的具体类型。
public class MyUtil {/*** 将集合元素打印到控制台上*/public static void print(List<?> lists){for (int i = 0; i < lists.size(); i++) {System.out.println(lists.get(i));}}/*** 上边界的定义: <? extends 具体类名>*          具体使用的时候,可以是上边界的任何子类型或者是本类型* @param list*/public static void print2(List<? extends Number> list){for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}/*** 下边界的定义:<? super 具体类名>*          具体使用的时候,可以是下边界的任何父类型或者本类型* @param*/public static void print3(List<? super Integer> list){for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}public static void main(String[] args) {List<Integer> nums = new ArrayList<Integer>();nums.add(1);nums.add(2);nums.add(3);MyUtil.print(nums);List<Long> ns = new ArrayList<Long>();ns.add(1L);ns.add(2L);ns.add(3L);MyUtil.print(ns);//上边界的测试:print2(new ArrayList<Long>());print2(new ArrayList<Number>());//print2(new ArrayList<Object>());  最高到达Number类型//下边界的测试:print3(new ArrayList<Integer>());print3(new ArrayList<Number>());print3(new ArrayList<Object>());//print3(new ArrayList<Long>());   Long和Integer没有关系。}
}

集合与数组

  1. 数组是定长的容器,一旦实例化完成,长度不能改变。集合是变长的,可以随时的进行增删操作。

  2. 数组中可以存储基本数据类型和引用数据类型的元素,集合中只能存储引用数据类型的元素。

  3. 数组的操作比较单一,只能通过下标进行访问。集合中提供了若干个方便对元素进行操作的方法

  4. 在存储引用类型时,集合与数组,存储的其实都是==对象的地址==

集合框架体系图

Collection接口

含义:Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义了他们三个子接口的共同方法。既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。作为父接口,其子类集合的对象,存储元素的特点,可能是无序的,也可能是有序的,因此在父接口中并没有定义通过下标获取元素的方法功能。

常用方法:

public class CollectionDemo {public static void main(String[] args) {//使用多态的向上造型创建一个子类型对象Collection<String> c1 = new ArrayList<>();//1. E add(E e)  向集合中添加元素c1.add("A");c1.add("B");c1.add("C");//2. boolean isEmpty()boolean empty = c1.isEmpty();System.out.println("empty: " + empty);//3. int  size(): 返回的是集合元素的个数System.out.println(c1.size());//4. String toString()System.out.println(c1);Collection<String> c2 = new ArrayList<>();c2.add("B");c2.add("C");c2.add("D");//5. addAll(Collection c)c1.addAll(c2);System.out.println(c1);/** 6. boolean contains(Object o):*    查看是否包含字符串 "B"*/boolean b = c1.contains("B");System.out.println("是否包含字符串B :"+b);/** 7. boolean containsAll(Collection c)*   查看c1是否包含c2*/boolean b1 = c1.containsAll(c2);System.out.println("c1集合是否包含c2集合:"+b1);/** 8. boolean  equals(Object o)*    测试: 创建一个新的集合c3  添加元素 "A" "B" "C" "B","D","D"*    判断两个集合是否相同*/Collection<String> c3 = new ArrayList<>();c3.add("A");c3.add("B");c3.add("C");c3.add("B");c3.add("C");c3.add("D");System.out.println("c1和c3相同吗?  :" + c1.equals(c3));/** 9.  boolean  remove(Object o)*     移除c1集合里的元素B,并查看剩下的元素       */boolean d = c1.remove("B");System.out.println(" 移除元素B :" + d);System.out.println(c1);/**  10.  boolean  removeAll(Collection<?> c)*       解析: 从集合中删除另一个集合c中所具有的元素。**      新建一个集合c4,  添加元素"B","C"*      测试c1移除子集c4                        */Collection<String> c4 = new ArrayList<>();c4.add("B");c4.add("C");c1.removeAll(c4);System.out.println(c1);/**   11.  boolean retainAll(Collection c)*      测试:向c1里添加"E","F","G",  然后保留子集c5,  c5里的元素有"A","E"   */c1.add("E");c1.add("F");c1.add("G");Collection<String> c5 = new ArrayList<>();c5.add("A");c5.add("E");c5.add("H");c1.retainAll(c5);System.out.println(c1);/** 12.  void clear():*      测试:清空c1                   */c1.clear();System.out.println(c1);System.out.println(c1.size());}
}

集合的迭代

1. 集合的迭代,就是指集合的遍历操作。2. 几乎所有的集合子类型都实现了迭代接口Iterable.

迭代接口提供的方法: 

boolean hasNext()     可以形象的认为有指针,指针的最初位置在第一个元素的前面。

E next()   用于返回指针指向的那个元素,然后指针向后移动,为下一次的判断。

E remove() 用于删除指针指向的那个元素。
在使用迭代器时,不可以调用集合自己的remove方法。
public class CollectionDemo02 {public static void main(String[] args) {Collection<Integer> c1 = new ArrayList();c1.add(1);c1.add(2);c1.add(3);c1.add(4);c1.add(5);for(Integer i: c1){System.out.print(i+"  ");
}
System.out.println();
//使用迭代器iterator进行遍历Iterator<Integer> it = c1.iterator();
while(it.hasNext()){Integer a = it.next;System.out.println("a:"+a);
}}}

迭代器的源码解析

三个成员变量:
*    cursor:  记录下一次要返回的元素的下标
*    lastRet:  记录上一次刚刚返回的元素的下标
*    expectedModCount:  预计的修改次数。 默认为集合的长度 ,与modCount的值息息相关
*                        注意:集合在调用add(E e)方法添加元素时,modCount++。
*
*    hasNext():    return  cursor!=size   : 当光标的值为集合长度时,没有下一个元素了。
*    next():
*        1. 检查 expectedModCount和modCount 是否一样,如果不一致,就抛异常。
*        2. 光标的值先赋值给lastRet。 相当于指针后移。 光标的值+1,为下一次的hasNext()做准备工作
*           新的lastRet的值就是指针指向的元素,也就是刚刚取出来的元素
*    remove():
*        1.  检查 expectedModCount和modCount 是否一样,如果不一致,就抛异常。
*        2.  调用ArrayList的  E remove(int index) 做真正的删除元素操作。
*            而E remove(int index)里面调用了System.arraycopy()方法,
*            从指定的index+1处,向前移动一位,以此形式做删除工作。
*
*            index的值是lastRet赋值的。
*
*            因为后续的元素向前移动了,因此cursor也要向前移动一次, 即cursor=lastRet.
*            如果不向前移动,会漏掉元素。 即 index+1这个位置上的元素,就会被漏掉。
*
*            最重要的是:  remove(int index)里面进行了modCount++操作。
*            但是 迭代器的remove里,进行重新赋值expectedModCount = modCount;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/396781.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年美国数学竞赛AMC8暑期备考:吃透625道真题和知识点(持续)

距离接下来最近的2025年AMC8美国数学竞赛还有几个月的时间&#xff0c;实践证明&#xff0c;做真题&#xff0c;吃透真题和背后的知识点是备考AMC8有效的方法之一。 通过做真题&#xff0c;可以帮助孩子找到真实竞赛的感觉&#xff0c;而且更加贴近比赛的内容&#xff0c;可以…

1915_开源C语言实现的通用队列

经常在工作中遇到一些队列处理的场景&#xff0c;以前要么是借用FreeRTOS这样的系统中的相关功能&#xff0c;要么是通过数组做一个简单的队列模型。但是&#xff0c;这两种方案都具有一定的局限性能&#xff0c;前者要求的FreeRTOS不见得相应的软件中有&#xff0c;而后者只能…

超好玩的肉鸽游戏:《暴君的游戏》手机单机游戏分享

《暴君的游戏》&#xff08;Despots Game&#xff09;是一款结合了自走棋和roguelike元素的像素策略冒险游戏。游戏以其独特的战斗系统和丰富的职业选择&#xff0c;为玩家提供了深度的策略体验和探索乐趣。 游戏特色包括&#xff1a; 角色职业多样性&#xff1a;玩家可以招募…

使用历史版本比对法排查C++程序中的内存泄漏问题

目录 1、问题描述 2、使用Process Explorer实时查看程序的虚拟内存占用 2.1、对于内存泄漏问题,需要查看程序占用的虚拟内存 2.2、Windows任务管理器中看不到程序进程占用的虚拟内存,使用Process Explorer工具可以看到 2.3、通过Process Explorer工具看到每次泄漏的内存…

大数据-75 Kafka 高级特性 稳定性-一致性保证 LogAndOffset(LEO) HightWatermark(HW) 水位/水印

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

LVS实战项目

LVS简介 LVS:Linux Virtual Server&#xff0c;负载调度器&#xff0c;内核集成&#xff0c;章文嵩&#xff0c;阿里的四层SLB(Server LoadBalance)是基于LVSkeepalived实现。 LVS集群的类型 lvs-nat &#xff1a; 修改请求报文的目标IP, 多目标 IP 的 DNAT lvs-dr &#xff…

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——6Resnet实现黑线识别

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——6Resnet实现黑线识别 ​ 比赛还有重要部分就是黑线的识别&#xff0c;这块地平线社区的帖子很多 ​ 在本次我就使用了社区吴超大佬写出的文章&#xff0c;当然我们的步骤有所不同&#xff0c;也是比较省…

黄牛杀手 抢票脚本 V3.0

黄牛杀手 抢票脚本 V3.0 介绍 现在黄牛太tm多了&#xff0c;根本抢不到票 为了解决这个问题&#xff0c;开发了这个脚本&#xff0c;支持大麦网&#xff0c;淘票票、缤玩岛等多个平台 依赖 selenium (4.10.0以下版本) pip install selenium 现在黄牛太tm多了&#xff0c;根…

2.类和对象(上)

1. 类的定义 1.1 类定义格式 • class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{ }中为类的主体&#xff0c;注意类定义结束时后面分号不能省略。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量; &#xff08;类和结构体非常像&#…

LVS原理——详细介绍

目录 lvs简介 LVS作用 LVS 的优势与不足 LVS概念与相关术语 LVS的3种工作模式 LVS调度算法 LVS-dr模式 LVS-tun模式 ipvsadm工具使用 lvs简介 LVS 是Linux Virtual Server的简称&#xff0c;也就是 Linux 虚拟服务器,是一个极好的负载均衡解决方案&#xff0c;它将一个…

计数排序,桶排序,基数排序

计数排序&#xff1a; 找出数据中的最大值和最小值&#xff0c;并创建哈希表&#xff0c;把 数据-最小值 作为数组的下标访问哈希表并标记数量&#xff0c;标记完后&#xff0c;遍历哈希表&#xff0c;当表中的值大于0&#xff0c;把 **下标最小值 (下标元素-最小值)**还原数据…

LLVM 寄存器分配

概述 基本寄存器分配器是四种寄存器分配器中最简单的寄存器分配pass实现(<llvm_root/livm/lib/CodeGen/RegAllocBasic.cpp>) 但麻雀虽小&#xff0c;五脏俱全&#xff0c;基本寄存器分配器中实现了根据溢出权重确实虚拟寄存器优先级、按优先级分配物理寄存器&#xff0…

韦东山瑞士军刀项目自学之UART

放自己一星期假回家&#xff0c;回来继续准备秋招。 本章记录关于UART协议的相关知识笔记。平时主要还是基于HAL库开发&#xff0c;但笔记里也讲了韦老师介绍的如何控制寄存器来设置UART的参数。 以及一些UART防止采集的抖动设置的一些策略与波特率与比特率的区别等。

文件共享服务NFS(服务名nfs,端口tcp/2049)

目录 前言 配置文件 工作原理 NFS服务器的配置 查看服务器是否安装 查看服务器状态 开启服务 编写配置文件 客户端挂载 前言 NFS&#xff08;Network File System&#xff09;是一种分布式文件系统协议&#xff0c;它允许网络中的不同计算机共享文件和目录&#xff0…

使用tailwindcss轻松实现移动端rem适配

本示例节选自小卷全栈开发实战系列的《Vue3实战》。演示如何用tailwindcss所支持的rem体系轻松实现一个仿b站移动端头部导航栏rem适配。 友情声明 学习分享不易&#xff0c;如果小伙伴觉得有帮助&#xff0c;点赞支持下。满30赞&#xff0c;将随文附赠录屏讲解&#xff0c;感谢…

树莓派4/5:运行Yolov5n模型(文末附镜像文件)

〇、前言 因国内网络问题&#xff0c;可直接烧录文末镜像文件&#xff0c;或者按照本教程进行手动操作。 一、实验目的 在树莓派4B运行Yolov5n模型。 二、实验条件 1、Windows 11计算机&#xff1a;安装了Mobaxterm 2、树莓派4B&#xff1a;64Bit Lite OS&#xff0c;安装了…

案例:Nginx + Tomcat集群(负载均衡 动静分离)

目录 案例 案例环境 案例步骤 部署Tomcat服务器 部署Nginx服务器 实现负载均衡和读写分离 日志控制 案例 案例环境 操作系统 IP 地址 角色 CentOS 192.168.10.101 Nginx服务器&#xff08;调度器&#xff09; CentOS 192.168.10.102 Tomcat服务器① CentOS 1…

uniapp 对于scroll-view滑动和页面滑动的联动处理

需求 遇到一个需求 解决方案 这个时候可以做一个内页面滑动判断 <!-- scroll-y 做true或者false的判断是否滑动 --> <view class"u-menu-wrap" style"background-color: #fff;"><scroll-view :scroll-y"data.isGo" scroll-wit…

贷奇乐漏洞学习 --- 两个变态WAF绕过

代码分析 第一个WAF 代码 function dowith_sql($str) {$check preg_match(/select|insert|update|delete|\|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is, $str);if ($check) {echo "非法字符!";exit();}return $str;} 实现原理 这段PHP代码定义了一个…

uniapp切换同一个子组件时,钩子函数只进了一次

给子组件添加不同的 “key” 值&#xff0c;当 key 值改变时&#xff0c;Vue 会认为这是一个不同的组件&#xff0c;并重新创建它 props: ["L1Id"],// 方式1: 使用keycomputed: {// 切换子组件时,发现created、mounted等钩子函数只会进一次,或者用 keykey(){this.ref…