当前位置: 首页 > news >正文

java加强 -Collection集合

集合是一种容器,类似于数组,但集合的大小可变,开发中也非常常用。Collection代表单列集合,每个元素(数据)只包含1个值。Collection集合分为两类,List集合与set集合。

特点

List系列集合:添加的元素有序,可重复,有指引。

即ArrayList、LinkedList:有序、可重复、有索引。

Set系列集合:添加的元素是无序、不重复、无索引。

HashSet:无序、不重复、无索引;

LinkedHashSet 有序、不重复、无索引。

TreeSet:按大小默认升序排序、不重复、无索引。

(Collection,List与Set是接口,ArrayList等集合是它们的实现类)

示例:

package Collection;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class CollectionDemo1 {public static void main(String[] args) {//目标:搞清楚Collection集合的整体特点//1、list家族的集合:有序,可重复,有索引List<String> list = new ArrayList<>();list.add("java");list.add("java");list.add("c++");list.add("python");System.out.println(list);for(int i = 0; i < list.size(); i++)System.out.println(list.get(i));//2、set家族的集合:无序,不可重复,无索引Set<String> set = new HashSet<>();set.add("java");set.add("java");set.add("c++");set.add("python");System.out.println(set);//无索引,没有get方法}
}

Collection集合的通用方法

package Collection;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;public class CollectionDemo2 {public static void main(String[] args) {//目标:搞清楚Collection集合的通用功能Collection<String> list = new ArrayList<>();//添加集合元素list.add("java");list.add("c++");list.add("python");System.out.println(list);//判断集合元素个数System.out.println(list.size());//删除集合元素list.remove("c++");System.out.println(list);//判断集合是否为空System.out.println(list.isEmpty());//清空集合list.clear();System.out.println(list.isEmpty());System.out.println(list);list.add("java");list.add("c++");//判断集合中是否包含某个元素System.out.println(list.contains("java"));System.out.println(list.contains("c++"));System.out.println(list.contains("python"));//集合转数组
//        Object[] arr = list.toArray();
//        for (int i = 0; i < arr.length; i++) {
//            System.out.println(arr[i]);
//        }String[] arr = list.toArray(String[]::new);System.out.println(Arrays.toString(arr));}
}

集合的几种遍历方式

通常,我们有三种方法可以遍历集合

一、迭代器遍历

package Collection;import java.util.ArrayList;
import java.util.Iterator;public class CollectionDemo3 {public static void main(String[] args) {//目标:理解集合的遍历方式//方式一:迭代器遍历ArrayList<String> names = new ArrayList<>();names.add("林青霞");names.add("张曼玉");names.add("王祖蓝");names.add("柳岩");names.add("张无忌");System.out.println(names);//1、得到一个迭代器对象Iterator<String> it = names.iterator();//it的位置是集合的第一个位置//System.out.println(it.next());      //取出当前位置数据,并且移动到下一个位置//while循环遍历while(it.hasNext()){    //判断当前位置有没有数据String name = it.next();System.out.println(name);}}
}

如上述代码,通过java库中Iterator<数据类型>变量名 来获取一个迭代器对象,用变量名.hasNext()来判断当前位置是否有值,没有值则不进入循环。再通过变量名.next获得当前位置数据,并将指针移向下一位数字来进行数据的输出。

二、增强for循环遍历

package Collection;import java.util.ArrayList;public class CollectionDemo4 {public static void main(String[] args) {//方式二:增强for循环遍历ArrayList<String> names = new ArrayList<>();names.add("林青霞");names.add("张曼玉");names.add("王");names.add("柳岩");names.add("张无忌");System.out.println(names);//可以遍历集合,也能遍历数组for(String name : names){System.out.println(name);}}
}

这是一个通用的方法,可以用于集合也可以用于数组,用name接收集合中的值并一个个将其打出。

三:Lambda方法:forEach遍历

package Collection;import java.util.ArrayList;
import java.util.function.Consumer;public class CollectionDemo5 {public static void main(String[] args) {//方式三:LambdaArrayList<String> names = new ArrayList<>();names.add("林青霞");names.add("张曼玉");names.add("王");names.add("柳岩");names.add("张无忌");//forEach(Consumer<? super T> action)//这是一个接口,所以需要使用Lambda表达式
//        names.forEach(new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });names.forEach(s -> System.out.println(s));}
}

通过重写集合中的accept方法进行遍历。

并发修改异常问题与解决

在遍历一个集合并对其中数据进行修改时,若是在循环中直接删掉一个数容易产生并发修改异常问题。例如,一个集合中有李明,李四,张三,王五 。当我们需要删除名字中带李的人时,遍历到李明时指针为0,李明被删除,数组上移一位,李四变为指针0,可此时指针已经移动到1的位置,李四被略过没删除,这就是并发修改异常问题。

示例

package Collection;import java.util.ArrayList;
import java.util.Iterator;public class CollectionDemo6 {public static void main(String[] args) {//目标:认识并发修改异常问题,搞清楚每种遍历的区别ArrayList<String> list = new ArrayList<>();list.add("Java入门");list.add("黑枸杞");list.add("宁夏枸杞");list.add("枸杞");list.add("特级枸杞");list.add("枸杞子");list.add("西洋参");System.out.println(list);//[Java入门, 黑枸杞, 宁夏枸杞, 枸杞, 特级枸杞, 枸杞子, 西洋参]for (int i = 0; i < list.size(); i++) {String s = list.get(i);if (s.contains("枸杞")){list.remove(s);}}System.out.println(list);   //枸杞没有删完//[Java入门, 宁夏枸杞, 特级枸杞, 西洋参]//原因是当遍历到了黑枸杞并删除时,此时索引变成了2,但因为黑枸杞被删了,宁夏枸杞的索引变成了1,所以索引为1的元素被跳过了System.out.println("========================================================");ArrayList<String> list2 = new ArrayList<>();list2.add("Java入门");list2.add("黑枸杞");list2.add("宁夏枸杞");list2.add("枸杞");list2.add("特级枸杞");list2.add("枸杞子");list2.add("西洋参");System.out.println(list2);//解决方案1:删除时索引-1
//        for (int i = 0; i < list2.size(); i++)
//            {
//                String s = list2.get(i);
//                if (s.contains("枸杞"))
//                {
//                    list2.remove(i);
//                    i--;//删除后索引要减一
//                }
//            }//方案二:倒着遍历 (支持索引)for (int i = list2.size()-1; i >=0 ; i--) {String s = list2.get(i);if (s.contains("枸杞"))list2.remove(s);}System.out.println(list2);System.out.println("========================================================");//三种遍历的区别ArrayList<String> list3 = new ArrayList<>();list3.add("Java入门");list3.add("黑枸杞");list3.add("宁夏枸杞");list3.add("枸杞");list3.add("特级枸杞");list3.add("枸杞子");list3.add("西洋参");System.out.println(list3);//一、迭代器遍历删除默认也存在并发修改异常问题Iterator<String> it = list3.iterator();while (it.hasNext()){String s = it.next();if (s.contains("枸杞"))//it.remove(s);it.remove();//用迭代器自己的方法删}System.out.println(list3);System.out.println("========================================================");ArrayList<String> list4 = new ArrayList<>();list4.add("Java入门");list4.add("黑枸杞");list4.add("宁夏枸杞");list4.add("枸杞");list4.add("特级枸杞");list4.add("枸杞子");list4.add("西洋参");System.out.println(list4);//二、三:增强for和Lambda(无法解决并发修改异常)
//        for (String s : list4) {
//            if (s.contains("枸杞"))
//                list4.remove(s);
//        }//结论:增强for和Lambda只适合做遍历,不适合遍历并修改
//        System.out.println(list4);list4.removeIf(s -> s.contains("枸杞"));System.out.println(list4);}
}

迭代器遍历内有专门解决这个问题的方法,即迭代器.remove(),删掉当前迭代器指向的值并且指针不动。用正常for循环时,可以用每删一个值指针就向前一位解决。还有一种方法就是从后往前遍历,删除后面的数据对前面的数据不造成影响,也可以正常删除。而增强for和Lambda则没有方法解决这个并发修改异常问题。因此,得出结论,增强for与Lambda适合用于遍历,而遍历同时进行修改则需要使用别的遍历方法。

相关文章:

  • HTML5表格语法格式详解
  • [Java实战]Spring Boot 中Starter机制与自定义Starter实战(九)
  • 端口号被占用怎么解决
  • 深入解析 Vision Transformer (ViT) 与其在计算机视觉中的应用
  • 计算机网络|| 常用网络命令的作用及工作原理
  • 罗技无线鼠标的配对方法
  • windows CUDA与CUDNN安装教程
  • 判断两台设备是否在同一局域网内的具体方法
  • MyBatis快速入门——实操
  • 基于VSCode + PlatformIO平台的ESP8266的DS1302实时时钟
  • 【安装配置教程】ubuntu安装配置Kodbox
  • POSIX信号量
  • Kubernetes生产实战(二十七):精准追踪Pod数据存储位置
  • I2C通讯
  • springboot3+vue3融合项目实战-大事件文章管理系统-参数校验优化
  • 【RAG】11种Chunking Strategies分块策略介绍和选择
  • 工具篇-扣子空间MCP,一键做游戏,一键成曲
  • C语言中#include引用头文件的尖括号和双引号的区别
  • 【音视频工具】ffplay介绍
  • 线程的一些事(2)
  • 中国至越南河内国际道路运输线路正式开通
  • 英国收紧移民政策,技术工作签证、大学招生面临更严要求
  • 中国目的地·入境游简报006|外国网红游中国启示录
  • 巴西总统卢拉抵达北京
  • 追光|铁皮房、土操场,这有一座“筑梦”摔跤馆
  • 大风暴雨致湖南岳阳县6户房屋倒塌、100多户受损