Java学习集合ArrayList、collection、Iterator迭代器、增强for循环、泛型
ArrayList集合
ArrayList是实现了动态数组的数据结构,与数组不同的是它在创建的时候不用指定大小,可以根据保存的内容自动增加容量。在不知道具体需要保存多少个数据的时候可以用ArrayList.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 练习:添加元素 import java.util.ArrayList; public void main (String[] args){ ArrayList<Integer> list= new ArrayList<Integer>(); list.add( 123 ); list.add( 234 ); list.add( 345 ); for ( int i= 0 ;i<list.size();i++){ System.out.println(list.get(i)); } } 添加指定类型的元素 public class demo { public static void main(String[] args) { ArrayList<Person> list = new ArrayList<Person>(); list.add( new Person( 18 , "张三" , "男" )); list.add( new Person( 58 , "李四" , "女" )); list.add( new Person( 28 , "李宝林" , "男" )); for ( int i = 0 ; i < list.size(); i++) { System.out.println(list.get(i)); } } } |
Collection接口
ArrayList类继承于抽象类AbstractList同时实现了接口List,而List又继承于Collection接口。即Collection是层次结构中的根接口。
Collection接口常用的基本方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public static void main(String[] args) { // 多态 父类引用指向子类对象 Collection<String> coll = new ArrayList<String>(); // 集合的add方法 coll.add( "张三" ); coll.add( "李四" ); coll.add( "王五" ); System.out.println(coll); // 集合转数组 Object[] arr = coll.toArray(); for ( int i = 0 ; i < arr.length; i++) { System.out.println(arr[i]); } // 集合中的remove方法 移除指定的元素 coll.remove( "李四" ); System.out.println( "移除后容器中元素的个数:" + coll.size()); // 集合中的contains方法 判断方法中是否有该元素 boolean b = coll.contains( "李四" ); System.out.println(b); // 集合中的clear方法 清除的是容器内的内容 coll.clear(); System.out.println(coll); } |
创建集合的方式
方式1:Collection<元素类型> 变量名 = new ArrayList<元素类型>(); //只能存储<>中指定的元素类型
方式2:Collection 变量名 = new ArrayList(); // 集合的元素类型默认为Object类型,即任何类型的元素都可以存储
Iterator迭代器
迭代器的使用,实质上就是循环遍历,且只能循环遍历,不能对集合进行增删改的操作
集合中把这种取元素的方法描述在iterator接口中,常用的方法有:
hasNext()方法:用来判断集合中是否有下一个元素可以迭代。如果返回true,说明可以迭代。
next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void main(String[] args) { Collection<String> coll = new HashSet<String>(); coll.add( "Hello World" ); coll.add( "你好,世界" ); coll.add( "好好学习,天天向上" ); // 迭代器的使用 实质就是循环遍历 // 获取iterator对象 Iterator<String> it = coll.iterator(); // 判断集合下一个是否有元素hasNext() //循环遍历 while (it.hasNext()){ String str=it.next(); System.out.println(str); } // 当it.hasNext()已经判断为false时,如果还想取元素,则会报异常 // java.util.NoSuchElementException // System.out.println(it.next()); //迭代器以for循环的形式使用 for (Iterator<String> it = coll.iterator(); it.hasNext();) { System.out.println(it.next()); } } |
在Collection接口描述了一个抽象方法iterator方法,所有Collection子类都实现了这个方法,并且有自己的迭代形式。
集合元素的向下转型
在集合中可以存储任意类型的元素,但是元素存进去之后就不原来的数据类型了,被提升为Object类型了。
要想提取出来,则需要向下转型。
1 2 3 4 5 6 7 8 9 10 11 12 | Collection coll = new ArrayList(); coll.add( "abc" ); coll.add( "aabbcc" ); coll.add( 1 ); Iterator it = coll.iterator(); while (it.hasNext()) { //由于元素被存放进集合后全部被提升为Object类型 //当需要使用子类对象特有方法时,需要向下转型 String str = (String) it.next(); System.out.println(str.length()); } 注:如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。 |
此时需要泛型登场了,Iterator接口也可以使用<>来控制迭代元素的类型的。
1 2 3 4 5 6 7 8 9 10 | Collection<String> coll = new ArrayList<String>(); coll.add( "abc" ); coll.add( "aabbcc" ); coll.add( "shitcast" ); Iterator<String> it = coll.iterator(); while (it.hasNext()) { String str = it.next(); //当使用Iterator<String>控制元素类型后,就不需要强转了。获取到的元素直接就是String类型 System.out.println(str.length()); } |
注:集合中存储其实都是对象的地址。
集合中可以存储基本数值吗?
jdk1.5版本以后可以存储了。因为出现了基本类型包装类,它提供了自动装箱操作(基本类型à对象),这样,集合中的元素就是基本数值的包装类对象。
增强for循环
//加强版for循环,又名foreach 只能遍历数组或者集合,不能进行增删改
//for(数据类型 变量名:目标容器){输出}
//数据类型 和 目标容器的类型一致。
1 2 3 4 | int [] arr = { 4 , 2 , 6 , 3 , 7 , 1 }; for ( int i : arr) { System.out.println(i); } |
泛型
集合中什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时 ClassCastException。此时使用集合时应该明确集合中元素的类型。即泛型
含有泛型的类
定义格式:修饰符 class 类名<代表泛型的变量> { } 如:public class ArrayList<String>{}
创建对象时,确定泛型的类型 如:ArrayList<String> list=new ArrayList<String>();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo6 { public static void main(String[] args) { Collection<String> arr = new ArrayList<String>(); arr.add( "asd" ); arr.add( "123" ); arr.add( "张三" ); String[] str = new String[arr.size()]; // 集合转数组 String[] str1 = arr.toArray(str); for (String str2 : str1) { System.out.println(str2); } System.out.println( "------------------" ); get(arr); Collection<Person> arr2 = new ArrayList<Person>(); arr2.add( new Person( 12 , "张三" , "男" )); get(arr2); } //定义方法时,无法确定具体集合中的类型是什么,就可以用通配符表示 //但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用 // 通配符? public static void get(Collection<?> coll) { Iterator<?> it = coll.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } |
泛型限定
如果想要对被打印的集合中的元素类型进行限制,只在指定的一些类型,进行打印。要解决这个问题,就要用到泛型的限定。
限定泛型的上限:
格式:? extends E
? 代表接收E类型或者E的子类型的元素
例如,泛型限定为:? extends Person
则 ? 代表接收Person类型或者Person子类型的元素
限定泛型的下限:
格式:? super E
? 代表接收E类型或者E的父类型的元素
例如,泛型限定为:? super Student
则 ? 代表接收Student类型或者Student父类型的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public static void main(String[] args) { ArrayList<Chef> arr1 = new ArrayList<Chef>(); arr1.add( new Chef( "老王" , "23" )); get(arr1); ArrayList<Fuwuyuan> arr2 = new ArrayList<Fuwuyuan>(); arr2.add( new Fuwuyuan( "老王" , "23" )); get(arr2); } //? extends 类 泛型的上限 //? super 类 泛型的下限 //利用泛型的上限 就可以调用Person类的work()方法,进而输出子类重写的work方法 public static void get(ArrayList<? extends Emp> arr) { Iterator<? extends Emp> it = arr.iterator(); while (it.hasNext()) { it.next().work(); } } public static void main(String[] args) { ArrayList<Chef> arr1 = new ArrayList<Chef>(); arr1.add( new Chef( "老王" , "23" )); get(arr1); ArrayList<Object> arr2 = new ArrayList<Object>(); arr2.add( new Fuwuyuan( "老王" , "23" )); get(arr2); } //? super 类 泛型的下限 //泛型的下限,只能接收Chef类型或者Chef的父类型的元素 //并不是所有父类都有work()方法,所以这里不能调用work方法 public static void get(ArrayList<? super Chef> arr) { Iterator<? super Chef> it = arr.iterator(); while (it.hasNext()) { it.next(); } } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具