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

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适合用于遍历,而遍历同时进行修改则需要使用别的遍历方法。

http://www.xdnf.cn/news/5429.html

相关文章:

  • Java基础语法之循环结构
  • immutable.js介绍
  • 【Diffusion】在华为云ModelArts上运行MindSpore扩散模型教程
  • 深入浅出之STL源码分析2_stl与标准库,编译器的关系
  • 解决VirtualBox中虚拟机(ubuntu)与主机(windows)之间互相复制粘贴(文本)
  • 文件批量重命名工具,简单高效一键完成更名
  • 【常用算法:排序篇】4.高效堆排序:线性建堆法与蚂蚁问题的降维打击
  • kubectl系列(十二):查询pod的resource 配置
  • Java定时任务
  • Cribl 利用CSV 对IP->hostname 的转换
  • tokenizer.encode_plus,BERT类模型 和 Sentence-BERT 他们之间的区别与联系
  • 数据结构练习:顺序表题目
  • terraform云上实战(一):执行阿里云云助手命令
  • C++ string初始化、string赋值操作、string拼接操作
  • Celery 在分布式任务调度中的实现原理及 MQ 系统对比
  • GIF图像技术介绍
  • 隐马尔可夫模型(HMM)在彩票预测中的Java实现
  • OpenCV进阶操作:指纹验证、识别
  • 复现MAET的环境问题(自用)
  • Javascript基础语法
  • 【STM32开发】-单片机开发基础(以STM32F407为例)
  • SEO长尾关键词布局优化法则
  • 虚拟内存笔记(三)虚拟内存替换策略与机制
  • 前端项目打包部署流程j
  • 北大闰凯博士:热辐射输运问题蒙特卡罗模拟中的全局最优参考场方法
  • HTOL集成电路老化测试学习总结-20250510
  • Linux : 多线程【线程概念】
  • ssh -T git@github.com 测试失败解决方案:修改hosts文件
  • 计算机基础
  • 深入了解linux系统—— 自定义shell