【JAVA】集合(Collection、Map)

集合和数组都是容器

数组:类型确定,长度固定,可以存储基本类型和引用类型的数据

集合:类型可以不固定,大小可变,只能存储引用数据类型的数据

Collection单列单列集合,每个元素只包含一个值
Map双列双列结合,每个元素包含两个值(键值对)

1 Collection

List(接口)系列集合:添加元素是有序、可重复、有索引

  • ArrayList、LinkedList(实现类):有序、可重复、有索引

Set(接口)系列结合:添加元素是无序、不重复、无索引的

  • HashSet(实现类):无序、不重复、无索引。LinkedHashSet:有序、不重复、无索引
// 不定义集合的数据类型
Collection list = new ArrayList();
// 定义集合的数据类型,只能支持引用数据类型
Collection<Integer> list = new ArrayList<>();
// 添加元素
list.add('a');
Collection hash = new HashSet();
// 添加元素
hash.add('a');

1.1 Collection

1.1.1 常用API 

public boolean add(E e)

把给定的对象添加到当前集合中

public void clear()

清空集合中所有的元素

public boolean remove(E e)

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

public boolean contains(Object obj)

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

public boolean isEmpty()

判断当前集合是否为空

public int size()

返回集合中元素的个数。

public Object[] toArray()

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

1.1.2 使用

如果希望元素可以重复,又有索引,索引查询要快?

  • 用ArrayList集合,基于数组的。(用的最多)

如果希望元素可以重复,又有索引,增删首尾操作快?

  • 用LinkedList集合,基于链表的。

如果希望增删改查都快。但是元素不重复、无序、无索引。

  • 用HashSet集合,基于哈希表的.

如果希望增删改查都快。但是元素不重复、有序、无索引。

  • 用LinkedHashSet集合,基于哈希表和双链表。

如果要对对象进行排序。

  • 用TreeSet集合,基于红黑树。后续也可以用List集合实现排序。

扩展知识

可变参数:可以接收多个数据(本质是一个数组)(一个形参列表可变参数只有一个,可变参数必须放在形参列表的最后)

// 数据类型...参数名称
public static void sum(int...nums){
}

1.1.3 Collections集合工具类

public static <T> boolean addAll(Collection<? super T> c, T... elements)

给集合对象批量添加元素

public static void shuffle(List<?> list)

打乱List集合元素的顺序

List<Integer> test = new Arraylist<>();
// 批量添加数据
Collection.addAll(test,1,2,3,4,5);
//打乱list集合顺序
Collection.shuffle(test);

排序(只针对list)

public static <T> void sort(List<T> list)

将集合中元素按照默认规则排序

public static <T> void sort(List<T> list,Comparator<? super T> c)

将集合中元素按照指定规则排序

Collections.sort(test);

方式一

  • 让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
// Student类里重写CompareTo方法
// 按年龄升序
@Override
public int compareTo(String o){return this.age - o.age;
}

方式二

  • 设置Comparator接口对应的比较器对象,来定制比较规则。
     
// 按年龄降序排
Collections.sort(stulist, new Comparator<Student>(){@Overridepublic int compare(Student o1,Student o2){return o2.getAge() - o1.getAge();}
});

1.2 List集合

有序、可重复、有索引

1.2.1 ArrayList

基于数组实现的,查询块,增删慢。

List<String> list = new ArrayList<>();
list.add("a");

void add(int index,E element)

在此集合中的指定位置插入指定的元素

E remove(int index)

删除指定索引处的元素,返回被删除的元素

E set(int index,E element)

修改指定索引处的元素,返回被修改的元素

E get(int index)

返回指定索引处的元素

删除重复相邻元素

foreach遍历删除、lambda表达式(会出现bug)

// 迭代器遍历删除
Iterator<String> it = list.iterator();while (it.hasNext()){String ele = it.next();if("Java".equals(ele)){list.remove("要删除元素");it.remove(); // 使用迭代器删除当期位置的元素,保证不后移,能够成功遍历到全部元素!}}
// for循环删除
for (int i = list.size() - 1; i >= 0; i--) {String ele = list.get(i);if("Java".equals(ele)){list.remove("要删除元素");}
}
// for循环删除2
for (int i = 0; i < list.size(); i++) {String ele = list.get(i);if("要删除元素".equals(ele)){list.remove("要删除元素");i--;}
}

1.2.2 LinkedList

基于双链表实现,查询慢,增删首尾元素快

LinkedList<string> a = new LinkedList<>();
a.addFirst("hhhh");

public void addFirst​(E e)

在该列表开头插入指定的元素

public void addLast​(E e)

将指定的元素追加到此列表的末尾

public E getFirst​()

返回此列表中的第一个元素

public E getLast​()

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

public E removeFirst​()

从此列表中删除并返回第一个元素

public E removeLast​()

从此列表中删除并返回最后一个元素

1.3 Set集合

无序、不重复、无索引

  • HashSet : 无序、不重复、无索引。
  • LinkedHashSet:有序、不重复、无索引。
  • TreeSet:排序、不重复、无索引。

Set集合的功能基本与Collection的API一致

Set<String> sets = new HashSet<>();
sets.add("aaa");

1.3.1 HashSet

采取哈希表存储

哈希表增删改查都很快(JDK8前,底层使用数组+链表组成;JDK8后,底层采用数组+链表+红黑树组成)

  • 哈希值是JDK根据对象的地址,按照某种规则算出来的int类型的数值
  • 同一对象多次调用hashCode​()方法,返回的哈希值相同;
  • 默认情况下,不同对象的哈希值是不同的
public int hashCode ​()
返回对象的哈希值
Set<String> sets = new HashSet<>();

1.3.1.1 LinkedHashSet

HashSet的子类,有序(存储和取出的顺序一致)、不重复、无索引

底层基于哈希表,使用双链表记录添加

1.3.2 TreeSet

不重复、无索引、可排序(按元素的大小默认升序排)

底层基于红黑树的数据结构实现排序,增删改查都很快

TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序

  • 对于数值类型:Integer , Double,官方默认按照大小进行升序排序。
  • 对于字符串类型:默认按照首字符的编号升序排序。
  • 对于自定义类型如Student对象,TreeSet无法直接排序。

对于没有默认规则的,需自定义规则(若这两个都定义了,则采用就近的规则)

方式一

  • 让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
// Student类里重写CompareTo方法
// 按年龄升序
@Override
public int compareTo(String o){return this.age - o.age;
}

方式二

  • TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。
     
// 按年龄降序排
Set<Student> s1 = new TreeSet<>(new Comparator<Student>(){@Overridepublic int compare(Student o1,Student o2){return o2.getAge() - o1.getAge();}
});

2 Map

Map集合每个元素是键值对,有点像字典类型

HashMap元素按照键是无序,不重复,无索引,值不做要求。Map体系一致
LinkedHashMap元素按照键是有序,不重复,无索引,值不做要求。
TreeMap元素按照建是排序,不重复,无索引的,值不做要求。
Map<String, Integer> maps = new HashMap<>();

2.1 常用API

V put(K key,V value)

添加元素

V remove(Object key)

根据键删除键值对元素

void clear()

移除所有的键值对元素

boolean containsKey(Object key)

判断集合是否包含指定的键

boolean containsValue(Object value)

判断集合是否包含指定的值

boolean isEmpty()

判断集合是否为空

int size()

集合的长度,也就是集合中键值对的个数

2.2 遍历方法

方式一:键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。

Set<K> keySet()获取所有键的集合
V get(Object key)根据值获取键

方式二:键值对的方式遍历,把“键值对“看成一个整体,难度较大。

Set<Map.Entry<K,V>> entrySet()

获取所有键值对对象的集合

getKey()

获得键

getValue()

获取值

 // 把Map集合转换成Set集合
Set<Map.Entry<String, Integer>> entries = maps.entrySet();  
Set entries = new HashSet();                                                                    
for (Map.Entry<String, Integer> entry : entries) {String key = entry.getKey(); // 取键Integer value = entry.getValue(); // 取值System.out.println(key + "==>" + value);
}

方式三:JDK 1.8开始之后的新技术:Lambda表达式。

default void forEach(BiConsumer<? super K, ? super V> action)

结合lambda遍历Map集合

// 简化前
maps.forEach(new BiConsumer<String, Integer>() {@Overridepublic void accept(String key, Integer value) {System.out.println(key + "===>" + value);}
});
// 简化后
maps.forEach((k,v) -> {System.out.println(k + "--->" + v);
});

2.3 HashMap*

HashMap是Map里面的一个实现类。

  • 特点都是由键决定的:无序、不重复、无索引
  • 底层是哈希表结构的。增删改查的性能都较好。
  • 依赖hashCode方法和equals方法保证的唯一。
  • 如果要存储的是自定义对象,需要重写hashCodeequals方法。

2.4 LinkedHashMap

  • 由键决定:有序(保证存储和取出的元素顺序一致)、不重复、无索引。
  • 原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序

2.5 TreeMap

  • 由键决定特性:不重复、无索引、可排序(按照键数据的大小默认升序(有小到大)排序。只能对键排序。)
  • TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序
  • TreeMap跟TreeSet一样底层原理是一样的。

TreeMap集合自定义排序规则有2

  • 类实现Comparable接口,重写比较规则。
  • 集合自定义Comparator比较器对象,重写比较规则。

3 遍历方式

迭代器

// 得到集合lists对象的迭代器对象
Iterator<String> it = lists.iterator();
while(it.hasNext()){// it.next() 获取元素String ele = it.next();System.out.println(ele);
}

foreach

Collection<String> list = new ArrayList<>();
...
for(String ele : list) {System.out.println(ele);
}

Lambda表达式

Collection<String> lists = new ArrayList<>();lists.forEach(s -> {System.out.println(s);});/**
lists.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}
});
**/

4 存储自定义对象

public class SystemDemo {public static void main(String[] args) {// 定义一个电影类的集合对象Collection <Movie> movies = new ArrayList<>();movies.add(new Movie("《肖生克的救赎》", 9.7,  "罗宾斯"));movies.add(new Movie("《霸王别姬》", 9.6 ,  "张国荣、张丰毅"));movies.add(new Movie("《阿甘正传》", 9.5,  "汤姆.汉克斯"));// 打出数组内容System.out.println(movies);// 遍历内容for (Movie movie : movies) {System.out.println("片名:" + movie.getName());System.out.println("评分:" + movie.getScore());System.out.println("主演:" + movie.getAcotr());}}
}
public class Movie {private String name;private double score;private String acotr;public Movie(String name, double score, String acotr) {this.name = name;this.score = score;this.acotr = acotr;}
}

集合中存储的是元素对象的地址

5 常见数据结构

栈:先进后出,后进先出

队列:先进先出,后进后出

数组:查询快,增删慢

  • 查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
  • 删除效率低:要将原始数据删除,同时后面每个数据前移。
  • 添加效率极低:添加位置后的每个数据后移,再添加元素。

链表:查询慢(数据从头开始查找),增删相对快

二叉树:只有一个根节点,每个节点最多支持两个直接子节点

查找二叉树

  • 每一个节点上最多有两个子节点
  • 左子树上所有节点的值都小于根节点的值
  • 右子树上所有节点的值都大于根节点的值
     

平衡二叉树:任意节点的左右两个子树的高度差不超过1,任意节点的左右两个子树都是一颗平衡二叉树

红黑数:一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。

红黑树增删改查性能都很好

  • 每—个节点或是红色的。或者是黑色的,根节点必须是黑色。、
  • 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,叶节点是黑色的。
  • 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)。
  • 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
     

6 泛型

  • 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
  • 泛型的格式:<数据类型>;注意:泛型只能支持引用数据类型。
  • 集合体系的全部接口和实现类都是支持泛型的使用的。

泛型的好处:

  • 统一数据类型。
  • 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来。

泛型类

// 修饰符 class 类名<泛型变量>{  }
public class MyArrayList<T> {  
}// 调用
MyArrayList<String> myl = new MyArrayList<>();

此处泛型变量T可以随便写为任意标识。常见的如E、T.K、V等。

作用:编译阶段可以指定数据类型,类似于集合的作用。

泛型方法

定义方法时同时定义了泛型的方法就是泛型方法。

// 修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}
public <T> void show(T t) {  }

作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性。

方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性

泛型接口

使用了泛型定义的接口就是泛型接口

// 修饰符 interface 接口名称<泛型变量>{}
public interface Data<E>{}

作用:泛型接口可以让实现类选择当前功能需要操作的数据类型,实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作。

通配符

? 可以在“使用泛型”的时候代表一切类型。

E T K V 是在定义泛型的时候使用的。

        ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());go(bmws);ArrayList<BENZ> benzs = new ArrayList<>();benzs.add(new BENZ());go(benzs);//        ArrayList<Dog> dogs = new ArrayList<>();
//        dogs.add(new Dog());
//        go(dogs);}/**定义方法,让汽车可以一起参加比赛*/
// ? extends Car: ?必须是Car或者其子类   泛型上限// ? super Car : ?必须是Car或者其父类   泛型下限public static void go(ArrayList<? extends Car> cars){}

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

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

相关文章

Node工程的依赖包管理方式

在前端工程化中&#xff0c;JavaScript 依赖包管理是非常重要的一环。依赖包通常是项目所依赖的第三方库、工具和框架等资源&#xff0c;它们能够帮助我们减少重复开发、提高效率并且确保项目可以正确的运行。 目前比较常见的前端包管理器有 npm 和 Yarn&#xff0c;npm 是 No…

Linux文件系统管理

Linux文件系统管理 磁盘的组成与分区 计算机用于存取文件的硬件是磁盘&#xff0c;磁盘的组成主要有磁盘盘、机械手臂、磁盘读取头与主轴马达所组成&#xff0c; 而数据的写入其实是在磁盘盘上面。磁盘盘上面又可细分出扇区(Sector)与磁道(Track)两种单位&#xff0c; 其中扇区…

浅谈JVM中的即时编译器(Just-In-Time compiler, JIT)

Java虚拟机&#xff08;JVM&#xff09;中的即时编译器&#xff08;Just-In-Time compiler, JIT&#xff09;是一个非常重要的组件&#xff0c;它负责将字节码转换为本地机器代码。在不使用JIT的情况下&#xff0c;JVM通过解释字节码来执行程序&#xff0c;这意味着它会为每个字…

C++RAII内存管理技术

文章目录 一.什么是RAII内存管理技术&#xff1f;二.智能指针unique_ptrshared_ptr循环引用问题weak_ptr 一.什么是RAII内存管理技术&#xff1f; C在引入异常机制后,代码执行流的跳转变得难以预料,如果使用普通的指针进行内存管理,很难避免内存泄漏的问题(执行流跳转导致堆区…

Linux文件属性查看和修改学习

一、基本属性 1、看懂文件属性&#xff1a; Linux系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位&#xff0c;拥有不同的权限。为了保护系统的安全性&#xff0c; Linux系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的…

无脑入门pytorch系列(三)—— nn.Linear

本系列教程适用于没有任何pytorch的同学&#xff08;简单的python语法还是要的&#xff09;&#xff0c;从代码的表层出发挖掘代码的深层含义&#xff0c;理解具体的意思和内涵。pytorch的很多函数看着非常简单&#xff0c;但是其中包含了很多内容&#xff0c;不了解其中的意思…

【Vue前端】设置标题用于SEO优化

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 1.vue全局配置2.创建并暴露getPageTitle方法3.通过全局前置守卫设置title4.页面上引用title5.项目使用中英文翻译&#xff0c;title失效 1.vu…

K8S系列三:单服务部署

写在前面 本文是K8S系列第三篇&#xff0c;主要面向对K8S新手同学&#xff0c;阅读本文需要读者对K8S的基本概念&#xff0c;比如Pod、Deployment、Service、Namespace等基础概念有所了解。尚且不熟悉的同学推荐先阅读本系列的第一篇文章《K8S系列一&#xff1a;概念入门》[1]…

mysql窗口函数

MySQl 8.0 窗口函数 窗口函数适用场景: 对分组统计结果中的每一条记录进行计算的场景下, 使用窗口函数更好, 注意, 是每一条!! 因为MySQL的普通聚合函数的结果(如 group by)是每一组只有一条记录!!! 可以跟Hive的对比着看: 点我, 特么的花了一晚上整理, 没想到跟Hive 的基本一致…

ntfy Delphi 相关消息接口文档

关联文档&#xff1a; ntfy 实现消息订阅和通知&#xff08;无需注册、无需服务器&#xff0c;太好了&#xff09;_海纳老吴的博客-CSDN博客群晖 nas 自建 ntfy 通知服务&#xff08;梦寐以求&#xff09;_海纳老吴的博客-CSDN博客 目录 一、消息实体对象接口 1. 消息发布方…

【MybatisPlus】LambdaQueryWrapper和QueryWapper的区别

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

自定义 视频/音频 进度条

复制代码根据自己需求改动就可以了 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><metaname"viewport"conten…