集合:List和Set

article/2025/8/25 5:09:02

集合

1.集合和数组之间的区别有:

  • 数组的长度是固定的,集合的长度是可变的
  • 数组中存储的是同一类型的元素,集合中存储的数据可以是不同类型的,除了泛型限制
  • 数组中可以存放基本类型数据或者对象,集合中只能存放对象,基本数据类型会自动装箱
  • 数组是由JVM中现有的 类型+[] 组合而成的,除了一个length属性,还有从Object中继承过来的方法 之外,数组对象就调用不到其他属性和方法了
  • 集合是由JavaAPI中的java.util包里面所提供的接口和实现类组成的,这里面定义并实现了很多方 法,可以使用集合对象直接调用这些方法,从而操作集合存放的数据

2.集合框架中主要有三个要素组成:

  • 接口       整个集合框架的上层结构,都是用接口进行组织的。 接口中定义了集合中必须要有的基本方法。 通过接口还把集合划分成了几种不同的类型,每一种集合都有自己对应的接口。
  • 实现类    对于上层使用接口划分好的集合种类,每种集合的接口都会有对应的实现类。 每一种接口的实现类很可能有多个,每个的实现方式也会各有不同。
  • 数据结构     每个实现类都实现了接口中所定义的最基本的方法,例如对数据的存储、检索、操作等方法。 但是不同的实现类,它们存储数据的方式不同,也就是使用的数据结构不同。

3.集合按照其存储结构可以分为两大类:

  •  java.util.Collection 单列集合  基本数据类型对应的包装器类型  list set queue 
  •  java.util.Map          双列集合  key-value      

      其他的集合接口,都是由这两个接口派生出来的,Collection父接口:Interable

4.Collection是父接口,其中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列 集合对象。 Collection类型集合必须要有的基本的方法:

//向集合中添加元素

boolean add(E e)

//把一个指定集合中的所有数据,添加到当前集合中 1 2 3

一些方法的使用样例:

boolean addAll(Collection c)

//清空集合中所有的元素。

void clear()

//判断当前集合中是否包含给定的对象。

boolean contains(Object o)

//判断当前集合中是否包含给定的集合的所有元素。

boolean containsAll(Collection c)

//判断当前集合是否为空。

boolean isEmpty()

//返回遍历这个集合的迭代器对象

Iterator iterator()

//把给定的对象,在当前集合中删除。

boolean remove(Object o)

//把给定的集合中的所有元素,在当前集合中删除。

boolean removeAll(Collection c)

//判断俩个集合中是否有相同的元素,如果有当前集合只保留相同元素,如果没有当前集合元素清空

boolean retainAll(Collection c)

//返回集合中元素的个数。

int size()

//把集合中的元素,存储到数组中。

Object[] toArray()

//把集合中的元素,存储到数组中,并指定数组的类型

T[] toArray(T[] a)

5.Vector

     since 1.0   java集合的开始,实现自动扩容,可变长数组,现在Vector成了Collection的子类,线程安全的集合

6.迭代器       

        为了能够方便的遍历集合中的每一个元素,API中提供了一个迭代器接口: java.util.Iterator 该接口可以很方便的迭代出集合中的元素。是Collection集合及其子类型集合通用的方式

        java.lang.Iterable 接口中,定义了获取迭代器的方法:

public interface Iterable {

        Iterator iterator();

}

        java.util.Iterator 接口中,主要定义俩个方法:

public interface Iterator {

boolean hasNext();    //返回当前迭代器中是否还有下一个对象

Object next();             //获取迭代器中的下一个对象

  }

7.foreach循环

   增强for循环      Collection类型及其子类型的集合,还有数组,都可以使用foreach循环进行遍历其中的元素数据

for(变量类型    变量名  :集合){

        //操作变量        

}

集合:

Collection c1 = new ArrayList<>();

c1.add("hello1");

c1.add("hello2");

c1.add("hello3");

for(Object o:c1){

        System.out.println(o);

}

数组:

int[] arr = {1,3,5,7,9};

//每次循环,使用变量i接收数组中的一个数据

for(int i : arr){

         System.out.println(i);

}

8.数据结构

(1)栈 :先进后出,弹栈、压栈

(2)队列 queue: 一端插入,另一端删除,先进先出

(3)数组 :连续的内存空间,数组查询速度快,中间删除较慢

(4)链表: 数据+下一个对象的地址值 单向链表,双向链表 查找元素慢,新增和删除元素较快

(5)红黑树:平衡二叉B树前序、中序、后序,左旋、右旋,保持平衡

        左子树都比根节点小,右子树都比根节点大

        红黑树的指定颜色的目的,是利用颜色值作为二叉树的平衡对称性的检查

  • 根节点必须是黑色
  • 其他节点可以是红色的或者黑色
  • 叶子节点(特指null节点)是黑色的
  •  每个红色节点的子节点都是黑色的
  • 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同

(6)哈希表  :数组+链表+红黑树

        哈希碰撞,哈希相同链表 链表长度默认是8,超过八转化为红黑树

 9.List集合:接口     (Collection)

(1)有序集合(而非排序),元素可以重复,带索引

(2)List接口常用方法:  还有从父接口Collection中继承过来的方法
 

//返回集合中指定位置的元素。

E get(int index);

//用指定元素替换集合中指定位置的元素,并返回被替代的旧元素。

E set(int index, E element);

//将指定的元素,添加到该集合中的指定位置上。

void add(int index, E element);

//从指定位置开始,把另一个集合的所有元素添加进来

boolean addAll(int index, Collection c);

//移除列表中指定位置的元素, 并返回被移除的元素。

E remove(int index);

//查收指定元素在集合中的所有,从前往后查到的第一个元素(List集合可以重复存放数据) int indexOf(Object o);

//查收指定元素在集合中的所有,从后往前查到的第一个元素(List集合可以重复存放数据) int lastIndexOf(Object o);

//根据指定开始和结束位置,截取出集合中的一部分数据

List subList(int fromIndex, int toIndex);

(3)List接口的实现类

  • ArrayList  :增删慢,查找快,使用数组来实现数据的存储

  • LinkedList :采用的数据结构是链表   还是一个双向链表

       LinkedList 类不仅实现了 List 接口,还有 Queue 接口以及子接口 Deque 也实现了

 //将指定元素插入此列表的开头

void addFirst(E e)

//将指定元素添加到此列表的结尾

void addLast(E e)

//返回此列表的第一个元素 E

getFirst()

//返回此列表的最后一个元素

E getLast()

//从此列表所表示的堆栈处弹出一个元素

E pop()

//将元素推入此列表所表示的堆栈

void push(E e)

//移除并返回此列表的第一个元素

E removeFirst()

//移除并返回此列表的最后一个元素

E removeLast()

 LinkedList 同时具有队列和栈的操作方法,pop和push都是栈结构的操作方法

  • VectorVector

   内部也是采用了数组来存储数据,但是 Vector 中的方法大多数都是线程安全的方法,所以在 多线并发访问的环境中,可以使用 Vector 来保证集合中元据操作的安全。

   查看 Vector 中方法的定义,可以看到多大数方法都使用了 synchronized 关键字,来给当前方法加 锁。

(4)list集合的索引:也有以下三种方式的遍历,还有一种根据索引进行遍历

迭代器、增强for循环、forEach

List list = new ArrayList(set);

for(int x=0;x<list.size();x++){

        Object o = list.get(x);

        System.out.println(o);

}

10.Set集合     (Collection)

(1)无序集合、不带下标索引、不能存放重复数据

Set set = new HashSet();

//用迭代器遍历

        Iterator it = set.iterator();

        while(it.hasNext()){

                Object obj = it.next();

        System.out.println(obj);

        }

//增强for循环遍历

for(Object obj : set){

        System.out.println(obj);

        }

//JDK8中的forEach遍历

(1)class ConsumerImpl implements Consumer{

        @Override

        public void accept(final Object o){

                System.out.println(o);

}

}

set.forEach(new ConsumerImpl());

(2)set.forEach(new Consumer(){

        

          @Override

        public void accept(final Object o){

                System.out.println(o);

}

});

//(3)接口中只有一个方法,lambda表达式  重写就可以省略

set.forEach(o->System.out.println(o));/

 

set.forEach(System.out::println);

(2)Set实现类

  • hashSet      底层:hashMap   (key,value)   值赋给key

        HashSet中元素不可重复,主要是靠对象的hashCode和equals方法来判断对象是否重复。

        若重复,就不会被传进来,而不是覆盖

  • TreeSet        (Set接口的子接口SortedSet的实现类)   底层:TreeMap   Conparable接口的compareTo方法保证不可重复

        TreeSet可以将我们存进去的数据进行排序,排序的方式有俩种:

        自然排序        int result = o1.compareTo(o2);     字符串:字典顺序排序

public static void main(String[] args) {

        Set set = new TreeSet();

         set.add(3);    //代码执行的时候,会自动进行装箱,把基本类型数据3变为Integer对象,然后再存放到集合中

        set.add(5);   //Integer类是实现了 Comparable 接口的,那么Integer类的俩个对象之间就可以调用 compareTo 方法比 较大小了,当前对象比较出来大小,那么对象就可以按照从小到大的顺序进行排序。

        set.add(1);

        set.add(7);

for(Object obj : set){

        System.out.println(obj);

        }

}

//输出结果:

1

3

5

7

        比较器排序(也称客户化排序)Set排序逻辑和业务逻辑不符时,自定义排序逻辑

public interface Comparator {   //指定泛型

        int compare(T o1, T o2);

}

public static void main(String[] args) {

//使用Comparator接口,创建出匿名内部类对象,这个对象就是要用的比较器对象

        Comparator c = new Comparator() {

                @Override

                public int compare(Object o1, Object o2) {

                        Student s1 = (Student) o1;          //

                        Student s2 = (Student) o2;         //  

                        return s1.age > s2.age? 1 : (s1.age==s2.age? 0 : -1);             //

        // return -s1.compareTo(s2);

        }

};

//创建TreeSet对象的时候,把比较器对象传入

        Set set = new TreeSet(c);

        set.add(new Student("mary",23));

        set.add(new Student("jack",21));

        set.add(new Student("tom",20));

        set.add(new Student("lucy",22));

        for(Object obj : set){

                System.out.println(obj);

        }

}

class Student implements Comparable{

        public int compareTo(Object o){

               Student that = (Student)o;

                return 0;

//Student rhat =(Student)o;

//先比name,name如果能产生结果,则整个就是name的结果

//如果name相等,再比age

//int nameComp = this.name.compareTo(that.name);

// int ageComp = this.age-that.age;

//  return nameComp ==0?ageComp:nameComp;

}

}

(3)java.util.Objects 是JDK1.7提供的一个对象的工具类,里面定义的一些静态方法,提供了操作 对象的方法   equals(Object a, Object b)       hash(Object... values)

     Arrays  工具类         

    Collections工具类

11.发展历程

Vector (单列)                           HashTable(双列)

List                                                Map

Collection(List、、(Vector)、        Map(    Hashtable)

                 Set(Map的key实现))             

12.List和Set

可以通过Set集合对List集合中的元素去重

List list=new ArrayList(Set);

Set set = new HashSet(list);

Set 集合和List集合都实现了对toString方法的重写

13.Map(双列)

(1)Set:Map的key     Map的value没有任何特性

Set添加元素:add   Map添加元素 :put

Map map = new HashMap();

map.put("张三",20);

map.put("张三",30);      

System.out.println(map);      //    {张三=30}  key值重复,会更新,然后把被覆盖的值返回

Set<K>              keySet()  获取Map集合中所有的key值

Collection<V>    values()   获取Map集合中所有的value值 

Set<Map.Entry<K,V>>   entrySet()   把Map集合中的key-value封装成Entry类型对象,再存放到set集合中,k-v当成一个元素

  Set<Map.entry>     entries = map.entrySet();
for(Map.entry entry: entries){

        Object key = entry.getKey();

        Object value = entry.getValue();

}

///getKey()   getValue()

(2)Map集合的遍历

(1)  通过get()方法

Set keys = map.keySet();

System.out.println(keys);

for(Object key:keys){

        Object value = map.get(key);

        System.out.println("value = "+value);

}

(2)拿到所有的Entry对象,再通过getKey()  getValue() 

Set<Map.entry>     entries = map.entrySet();
for(Map.entry entry: entries){

        Object key = entry.getKey();

        Object value = entry.getValue();

}

(3)  jdk8中的forEach  

14.练习

public class Student{
//练习//编写Student(String name,int age)类//创建多个Student类的对象//将其存储在List集合中,对List集合进行迭代遍历//判断 如果名字叫“张三”,从List中移除该对象String name;int age;Student(String name,int age){this.age=age;this.name=name;}
}
class StudentTest {public static void main(String[] args) {Student stu1=new Student("赵六",20);Student stu2=new Student("李四",22);Student stu3=new Student("张三",24);Student stu4=new Student("王五",25);List list=new ArrayList<>();list.add(stu1);list.add(stu2);list.add(stu3);list.add(stu4);Iterator iterator = list.iterator();while(iterator.hasNext()) {Student s = (Student)iterator.next();System.out.println(s);if ("张三".equals(s.name)){list.remove(s);}}}}

并发修改异常:两个及以上不属于同一个对象的行为在操作同一个集合

 原因:迭代器初始化在-1,类似于指针,通过集合长度和索引值+1判断有没有下个元素,将张三移除后,后面元素补上,长度改变 ,索引值+1=长度,认为后边没有元素   

Iterato是一次性的,知道有下一个元素hasNext(),但是取不出来 ,先获取的迭代器,再在list中添加

hasNext()决定理论上能不能移,next()决定实际上能不能移,增强for循环底层也是迭代器

解决方案:只针对list集合,set没有解决方法,增强for循环也会出现并发修改异常 

迭代器 listIterator  ,只能解决并发修改问题,迭代器添加元素只会在当前位置添加,不会添加在最后  litr.add("kevin",20),不管移不移除张三,都取不到kevin

ListIterator litr = list.listIterator();while (litr.hasNext()){Student s=(Student)litr.next();System.out.println(s);if("张三".equals(s.name)){litr.remove();}

通过索引遍历, 不会出现并发修改异常

for(int x=0;x<list.size();x++){Student s=(Student)list.get(x);System.out.println(s);if("张三".equals(s.name)){list.remove(s);list.add(new Student("kevin",20));}


http://chatgpt.dhexx.cn/article/buvXXDGL.shtml

相关文章

List集合,Set集合

List集合: 1 ArrayList集合&#xff1a; 优点&#xff1a;查找快 缺点&#xff1a; 元素增删慢 注&#xff1a;日常开发使用最多的功能就是查询数据&#xff0c;遍历数据&#xff0c;所以该集合是最常用的集合。 常用方法&#xff1a; 方法测试&#xff1a; 新建一个集合添…

集合Set

集合的一个关键的特点就是不能存放重复的元素&#xff0c;二分搜索树是一个非常好的实现集合的底层数据结构 1、二分搜索树实现集合&#xff1a; set接口 package Set;public interface Set<E> {void add(E e);boolean contains(E e);void remove(E e);int getSize();b…

C++ 集合set 详解

1.关于set C STL 之所以得到广泛的赞誉&#xff0c;也被很多人使用&#xff0c;不只是提供了像vector, string, list等方便的容器&#xff0c;更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组&#xff0c;list封装了链表&#xff0c;map和se…

set集合使用详解

set集合使用详解 “曾经年少爱追梦&#xff0c;一心只想往前飞。”那会高二&#xff0c;刚刚接触c语言&#xff0c;一发不可收拾&#xff0c;还记得当时为了一个想法和朋友一起想到半夜。现在我还是那个少年&#xff0c;那个又菜又爱玩的少年。 咳咳&#xff0c;set集合容器&am…

OBS录屏如何设置录制窗口大小?

1、在显示录制窗口区右键→滤镜→添加一个裁剪/填充→调整左右顶底部里的数字进行裁剪&#xff0c;调整到合适的录屏大小即可。

如何使用OBS 进行屏幕录制

软件界面 默认的保存位置 C:\Users\XXXX\Videos 如何对屏幕进行录制&#xff08;默认也录制了音频信号&#xff09;

obs屏幕录制暂停

OBS Studio 24.0 RC1 发布 – 有大惊喜OBS Studio 24.0 RC1 发布 – 有大惊喜 OBS Studio 24.0 RC1于今天下午发布&#xff0c;增加了在录制时暂停的功能&#xff0c;允许“无缝地实时删除视频片段”。OBS Studio 24.0 RC1还支持在发生拥塞时自动调整比特率&#xff0c;而不是丢…

OBS录屏软件使用指南

OBS录屏软件使用指南 1 简介2 录屏使用步骤2.1 来源2.2 设置2.2.1 输出2.2.2 视频 2.3 录制 3 总结 1 简介 2 录屏使用步骤 2.1 来源 在来源标签&#xff0c;添加显示器捕获。 2.2 设置 在录屏时&#xff0c;需要进行录屏设置&#xff0c;点击菜单栏文件->设置 2.2.1…

【录屏】OBS如何区域录制

OBS如何区域录制 按住alt拖动红色边框即可隐藏拖动的区域

OBS 录制简单操作说明

把从B站Sky灬素颜看到的关于OBS录制视频的部分文字记录下 视频地址 录制界面捕获 1.首先&#xff0c;新建一个场景。 2.在新建的场景下&#xff0c;点击右边的来源窗口&#xff0c;新建一个捕获方式。 &#xff08;此处注意被捕获的窗口不能最小化&#xff0c;需要浮在桌…

OBS录制黑屏的解决办法

前些时间打开下载了好久一直没打开的obs录屏软件&#xff0c;想把老师的直播网课录下来重复看&#xff0c;但是发现&#xff0c;无论是用显示器捕获还是窗口捕获都是黑屏&#xff0c;然后就百度找了挺多关键词的&#xff0c;有的方法奏效有的不行有的不全面&#xff0c;为了方便…

obs直播录屏软件下载使用教程-制作短视频录制视频教程

现在是短视频的时代&#xff0c;我们需要学一点视频处理技术&#xff0c;录屏也是一项基本能力 下载软件 这里我下载的是obs软件&#xff0c;可以录屏可以直播 https://obsproject.com/ 因为网络原因&#xff0c;一直没有下载成功&#xff0c;开启特殊上网&#xff0c;才算一点…

OBS录制设置基本介绍(1)

1.OBS OBS&#xff08;Open Broadcasting Software&#xff09;是一款免费且开源的跨平台直播和录制软件&#xff0c;它可以将电脑屏幕、摄像头、麦克风和音频源等多种内容混合在一起并进行直播或录制。 1)基本操作介绍&#xff1a; 下载 OBS官网 在OBS官网&#xff08;htt…

直播、录屏软件OBS Studio下载安装操作教程

直播、录屏软件OBS Studio下载安装操作教程 OBS Studio是一款非常强大的免费开源无广告&#xff0c;国外开发的软件&#xff0c;录屏只是它的一部分功能&#xff0c;对于需要录制屏幕又要录制摄像头的也很适合&#xff0c;比如现在的直播行业&#xff0c;这款软件是一个不二之…

录屏软件OBS录屏时噪声大的解决办法

1、选择麦克风的滤镜 2、点击右下角号&#xff0c;选择噪声抑制 3、点击确定即可&#xff0c;这样设置就完成了&#xff0c;最后关闭滤镜就可以无噪声录制视频了 你的点赞、评论、收藏和关注是我创作的动力。 感谢各位看官老爷

解决OBS录屏软件窗口采集不全的问题

问题描述 使用OBS录屏软件的窗口采集功能的时候&#xff0c;有时候窗口对象只能捕获到一部分&#xff0c;不能全屏都是目标对象。 解决办法

OBS视频录制及其直播推流教程(超详细,非硬核)

录制软件&#xff1a; OBS &#xff08;我用过很多录制软件&#xff0c;OBS是最好用的&#xff0c;没有之一&#xff0c;而且完全免费&#xff09; 功能&#xff1a;直播&#xff0c;录像&#xff08;录制游戏或者网课等等&#xff09; 我准备将我的教程分为多个部分&#xf…

OBS 安装与考试参数设置及屏幕无法完全捕获、录屏不完整的解决方法

目录 一、OBS 的下载与安装 二、OBS 考试参数设置 三、问题解决 &#xff08;1&#xff09;屏幕无法完全捕获 &#xff08;2&#xff09;录屏不完整 一、OBS 的下载与安装 官网&#xff08;Open Broadcaster Software | OBS&#xff09;选择对应的版本下载&#xff0c;自…

OBS 录制没有声音怎么办?

1.检查obs设置- 音频 -是否是默认选项 2.检查win10 是否允许使用麦克风 1&#xff09;右下角出现麦克风标识 2&#xff09;设置-隐私-麦克风&#xff0c;查看允许放开你的麦克风是否打开 如果上述还是为解决问题&#xff0c;那么接下来的就是关键 3. 控制面板 - 硬件和声音 …

20221130如何修改OBS录屏的存储路径?

obs https://obsproject.com/ OBS OBS Open Broadcaster Software OBS Studio Latest Release 28.1.2 - November 5th obs 录屏 更换保存位置 https://jingyan.baidu.com/article/67508eb4c854fbddca1ce481.html 20221130如何修改OBS录屏的存储路径&#xff1f; 如何修改OBS录…