(一)、Set系列集合
Set系列集合特点

  • 无序:存取顺序不一致
  • 不重复:可以去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。

Set集合实现类特点

  • HashSet : 无序、不重复、无索引。//get()取不到值,第一次运行顺序统一
  • LinkedHashSet:有序、不重复、无索引。
  • TreeSet:排序、不重复、无索引。

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

实现类:HashSet集合元素无序的底层原理:哈希表

  • HashSet集合底层采取哈希表存储的数据。
  • 哈希表是一种对于增删改查数据性能都较好的结构。

哈希表的组成

  • JDK8之前的,底层使用数组+链表组成
  • JDK8开始后,底层采用数组+链表+红黑树组成。

哈希值

  • 是JDK根据对象的地址,按照某种规则算出来的int类型的数值。

Object类的API

  • public int hashCode​():返回对象的哈希值

对象的哈希值特点

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的。//因为地址不同
public class SetDemo2 {public static void main(String[] args) {//目标:学会获取对象的哈希值,并确认String name = "Java";System.out.println(name.hashCode());System.out.println(name.hashCode());String name1 = "java";System.out.println(name1.hashCode());System.out.println(name1.hashCode());}
}

HashSet1.7版本原理解析:数组 + 链表  +(结合哈希算法)

  1. 创建一个默认长度16的数组,数组名table
  2. 根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法)
  3. 判断当前位置是否为null,如果是null直接存入
  4. 如果位置不为null,表示有元素,则调用equals方法比较
  5. 如果一样,则不存,如果不一样,则存入数组,
  • JDK 7新元素占老元素位置,指向老元素
  • JDK 8中新元素挂在老元素下面

结论:哈希表是一种对于增删改查数据性能都较好的结构。

JDK1.8版本开始HashSet原理解析

  • 底层结构:哈希表(数组、链表、红黑树的结合体)
  • 当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树。
import java.util.HashSet;
import java.util.Set;public class SetDemo3 {public static void main(String[] args) {Set<Student> sets = new HashSet<>();Student s1 = new Student("aaa",12,'a');Student s2 = new Student("aaa",12,'a');Student s3 = new Student("bbb",12,'a');System.out.println(s1.hashCode());System.out.println(s2.hashCode());System.out.println(s3.hashCode());sets.add(s1);sets.add(s2);sets.add(s3);System.out.println(sets);}
}

比较哈希值,对象元素相等哈希值也相等,比较然后剔除
如果希望Set集合认为2个内容相同的对象,就重写对象的hashCode和equals方法。
不重写,重复值就依然重复!

LinkedHashSet集合概述和特点

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

LinkedHashSet集合的特点和原理

  • 有序、不重复、无索引
  • 底层基于哈希表,使用双链表记录添加顺序。

TreeSet集合概述和特点

  • 不重复、无索引、可排序
  • 可排序:按照元素的大小默认升序(有小到大)排序。
  • TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
  • 注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。

TreeSet集合默认的规则

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

结论:想要使用TreeSet存储自定义类型,需要制定排序规则

自定义排序规则:TreeSet集合存储对象的的时候有2种方式可以设计自定义比较规则
方式一 :让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
方式二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。
两种方式中,关于返回值的规则:

  • 如果认为第一个元素大于第二个元素返回正整数即可。
  • 如果认为第一个元素小于第二个元素返回负整数即可。
  • 如果认为第一个元素等于第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复。

注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;public class SetDemo5 {/*目标:观察TreeSet对于有值特征的数据如何排序* 学会自定义类型的对象进行指定规则排序*/public static void main(String[] args) {Set<Integer> sets = new TreeSet<>();sets.add(23);sets.add(65);sets.add(11);sets.add(45);System.out.println(sets);Set<String> set1 = new TreeSet<>();set1.add("Java");set1.add("Jcva");set1.add("Jdva");set1.add("Java1");System.out.println(set1);System.out.println("--------------");Set<Student1> xs = new TreeSet<>((Student1 o1, Student1 o2)-> {return o1.age - o2.age >= 0 ? 1:-1;//注意:浮点型建议使用Double.compare()});xs.add(new Student1("aaa",12,'a'));xs.add(new Student1("dxdx",31,'h'));xs.add(new Student1("fsaf",63,'t'));xs.add(new Student1("aaa",2,'l'));System.out.println(xs);}
}
//implements Comparable<Student1>
/*public int compareTo(Student1 o) {
*       return this.age - o.age >= 0 ? 1:-1;//可保留
*      //return this.age - o.age; 会去掉重量重复的元素
* }
*/

(二)、补充知识:可变参数
可变参数的特点

  • 可变参数用在形参中可以接收多个数据。
  • 可变参数的格式:数据类型...参数名称

可变参数的作用

  • 接收参数非常灵活方便。可以不接收参数,可以接收1个或者多个参数,也可以接收一个数组
  • 可变参数在方法内部本质上就是一个数组。
public class MethodDemo {public static void main(String[] args) {sun();//不传参数sun(2);sun(new int[] {10,20,10,29});//也可传数组}public static void sun(int...nums){//注意:可变参数在方法内部就是一个数组,numsSystem.out.println("元素个数:" + nums.length);System.out.println("元素内容:" + Arrays.toString(nums));}
}

可变参数的注意事项:(防止冲突)

  • 一个形参列表中可变参数只能有一个//(int...age,int...ages)
  • 可变参数必须放在形参列表的最后面//  (int age,int...ages)正确,(int...age,int ages)

(三)、斗地主游戏案例分析
需求: 在启动游戏房间的时候,应该提前准备好54张牌,完成洗牌、发牌、牌排序、逻辑。
分析:

  • 当系统启动的同时需要准备好数据的时候,就可以用静态代码块了。
  • 洗牌就是打乱牌的顺序。
  • 定义三个玩家、依次发出51张牌
  • 给玩家的牌进行排序(拓展)
  • 输出每个玩家的牌数据。
public class Card {private String size;private String color;private int index;//牌的真正大小public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}public String getSize() {return size;}public void setSize(String size) {this.size = size;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public Card(String size, String color,int index) {this.size = size;this.color = color;this.index = index;}public Card() {}@Overridepublic String toString() {return size + color;}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;public class GameDemo {//定义一个静态的集合存储54张牌对象public static List<Card> allCards = new ArrayList<>();//做牌,定义静态代码块初始化派数据static{//定义点数:个数确定,类型数据,使用数组String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};String[] colors = {"ht","hot","hm","hom"};int index = 0;for (String s : sizes) {index++;for (String s1 : colors) {Card c = new Card(s,s1,index);allCards.add(c);}}Card c1 = new Card("","xking",++index);Card c2 = new Card("","xking",++index);Collections.addAll(allCards,c1,c2);System.out.println("新增:" + allCards);}public static void main(String[] args) {//洗牌Collections.shuffle(allCards);System.out.println("洗牌过后:" + allCards);//发牌List<Card> l1 = new ArrayList<>();List<Card> l2 = new ArrayList<>();List<Card> l3 = new ArrayList<>();//开始发牌for (int i = 0; i < allCards.size()-3; i++) {Card c = allCards.get(i);if(i%3==0){l1.add(c);}else if(i%3==1){l2.add(c);}else if (i%3==2){l3.add(c);}}//最后拿,组成子集合List<Card> lastThreeCards = allCards.subList(allCards.size()-3,allCards.size());sortCards(l1);sortCards(l2);sortCards(l3);//输出牌System.out.println("l1: " + l1);System.out.println("l2: " + l2);System.out.println("l3: " + l3);System.out.println("最后三张牌:" + lastThreeCards);}private static void sortCards(List<Card> cards){Collections.sort(cards, new Comparator<Card>() {@Overridepublic int compare(Card o1, Card o2) {return o2.getIndex() - o1.getIndex();}});}
}

(四)、Map集合体系
Map集合概述和使用

  • Map集合是一种双列集合,每个元素包含两个数据。
  • Map集合的每个元素的格式:key=value(键值对元素)。
  • Map集合也被称为“键值对集合”。

Map集合整体格式

  • Collection集合的格式: [元素1,元素2,元素3..]
  • Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}

Map集合的使用场景之一:购物车系统 -> {商品1=2 , 商品2=3 , 商品3 = 2  , 商品4= 3}

  • 购物车提供的四个商品和购买的数量在后台需要容器存储。
  • 每个商品对象都一一对应一个购买数量。
  • 把商品对象看成是Map集合的建,购买数量看成Map集合的值。

Map集合体系特点

  • Map集合的特点都是由键决定的。
  • Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)。
  • Map集合后面重复的键对应的值会覆盖前面重复键的值。
  • Map集合的键值对都可以为null。

Map集合实现类特点

  • HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)
  • LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
  • TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
import java.util.HashMap;
import java.util.Map;//目标:认识Map体系
public class MapDemo1 {public static void main(String[] args) {//创建一个Map集合对象Map<String,Integer> maps = new HashMap<>();maps.put("java" ,3);maps.put("python" ,7);maps.put("c语言" ,null);maps.put("go语言" ,4);maps.put(null ,null);System.out.println(maps);}
}

Map集合API

public class MapDemo1 {public static void main(String[] args) {//创建一个Map集合对象Map<String,Integer> maps = new HashMap<>();//Map集合的API接口//添加元素maps.put("java" ,3);maps.put("python" ,7);maps.put("python" ,10);//相同键,对应的值会被后者覆盖maps.put("c语言" ,null);maps.put("go语言" ,4);maps.put(null ,null);System.out.println(maps);//清空集合//maps.clear();//判断集合是否为空System.out.println(maps.isEmpty());//获取键后面对应的值Integer key = maps.get("python");System.out.println(key);//根据键删除整个元素System.out.println(maps.remove("go语言"));System.out.println(maps);//是否包含某个键System.out.println(maps.containsKey("c语言"));System.out.println(maps.containsKey("b语言"));//是否包含某个值System.out.println(maps.containsValue(100));System.out.println(maps.containsValue(12));//获取全部键,public Set<K> keySet();Set<String> key1 = maps.keySet();System.out.println(maps.keySet());//获取全部值的集合 Collection<V> value();Collection<Integer> value = maps.values();System.out.println(maps.values());//集合大小System.out.println(maps.size());//合并其他的Map集合Map<String,Integer> nap1 = new HashMap<>();nap1.put("java",1);nap1.put("java1",5);Map<String,Integer> nap2 = new HashMap<>();nap1.put("java2",2);nap1.put("java3",4);nap1.putAll(nap2);//将nap2拷贝到nap1里面}
}

Map集合遍历

import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapDemo2 {public static void main(String[] args) {Map<String,Integer> nap1 = new HashMap<>();nap1.put("java" ,3);nap1.put("python" ,7);nap1.put("go语言" ,4);System.out.println(nap1);/linkedHash,输入有序,重复替换原处//键找值,方法一//先拿到集合的全部键Set<String> key = nap1.keySet();for (String s : key) {int value = nap1.get(s);System.out.println(s + "值" + value);}//键值对 方法二//可以调用Map方法 entrySet把Map集合换成Set集合(Map集合键值对元素没有类型)//赋予类型,Map.Entry<String,Integer>//Set<Map.Entry<String,Integer>> entries    //小技巧,ctrl+alt+v补全代码Set<Map.Entry<String, Integer>> entries = nap1.entrySet();System.out.println(entries);//开始遍历for (Map.Entry<String, Integer> entry : entries) {String key1 = entry.getKey();int value = entry.getValue();System.out.println(key1 + "值" + value);}//lambda表达式遍历nap1.forEach((key1, value) -> {System.out.println(key1 + "值" + value);});}
}

Map集合案例分析

import java.util.HashMap;
import java.util.Map;
import java.util.Random;//案例:80人去A\B\C\D景点,只选择一个,那个景点去的人多
public class MapDemo3 {public static void main(String[] args) {//把80个学生选择的数据拿过来String[] selects = {"A","B","C","D"};StringBuilder sb = new StringBuilder();Random r = new Random();for (int i = 0; i < 80; i++) {sb.append(selects[r.nextInt(selects.length)]);}System.out.println(sb);//map集合记录选择的结果Map<Character,Integer> infe = new HashMap<>();//遍历数据for (int i = 0; i < sb.length(); i++) {//获取选取字符char ch = sb.charAt(i);//判断是否存在此键if(infe.containsKey(ch)){//其值计数加一,put()键相同,取最新更新的值infe.put(ch,infe.get(ch)+1);}else {//刚开始计数infe.put(ch,1);}System.out.println(infe);}}
}

TreeMap<>();与set方法一致
Map<Student,String> map = new TreeMap<>();
有this中比较对象重复就覆盖

(五)、集合嵌套

import java.util.*;public class MapTest {public static void main(String[] args) {//一个学生选择多个Map<String, List<String>> data = new HashMap<>();//选择的存进去List<String> selects = new ArrayList<>();Collections.addAll(selects,"A","C");data.put("aaa",selects);List<String> selects1 = new ArrayList<>();Collections.addAll(selects1,"A","C","D");data.put("bbb",selects1);System.out.println(data);//统计选择人数Map<String,Integer> infe = new HashMap<>();//只是为了存东西进去//提取信息Collection<List<String>> value =  data.values();for (List<String> values : value) {//数组for (String s : values) {//数组里面的数据if(infe.containsKey(s)){//其值计数加一,put()键相同,取最新更新的值infe.put(s,infe.get(s)+1);}else {//刚开始计数infe.put(s,1);}}}System.out.println(infe);}
}

java进阶开发-----Set集合、Map集合(接java集合)相关推荐

  1. 视频教程-Java进阶高手课-Spring精讲精练-Java

    [ [这里是图片001] Java进阶高手课-Spring精讲精练 中国科学技术大学硕士研究生,丹麦奥尔堡大学访问学者,先后就职于eBay.蚂蚁金服.SAP等国内外一线互联网公司,在Java后端开发. ...

  2. java遍历嵌套二维map输出下标_Map集合嵌套 4种遍历方式

    package com.oracle.demo01; import java.util.HashMap; import java.util.Iterator; import java.util.Map ...

  3. 零基础学java web开发_从零基础学Java成为一个专业的java web 开发者

    原标题:从零基础学Java成为一个专业的java web 开发者 "我怎么才能成为一个Java Web开发者?"对于这个问题,答案其实并不简单.成为一个Java Web开发人员包括 ...

  4. java agent 开发_IDEA + maven 零基础构建 java agent 项目

    Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说,这个东西还是比较神奇和陌生的:虽说在实际的业务开发中,很少会涉及到 agent ...

  5. java关闭通道_调用map方法后,Java 7文件通道未正确关闭

    我正在研究一个sc2replay解析工具.我在MPQLIB http://code.google.com/p/mpqlib/之上构建它 不幸的是,该工具使用文件通道来读取bzip文件, 并使用map( ...

  6. java后端开发需要会什么技能,从事Java后端开发,需要掌握哪些知识和技能?

    很多小伙伴想转行做Java的后端,但是又不知道到底该学习些什么,做Java的后端,需要学习和了解什么? 1.首先要明确后端包括哪些职业 DBA(数据库维护优化专家) Developer(程序猿) Ar ...

  7. java后端开发需要学什么_从事Java后端开发,要学习哪些知识和技能?

    首先要明确后端包括哪些职业:DBA(数据库维护优化专家),Developer(程序猿),Architect(构架师),Scrum master及类似(敏捷开发专家),Project Manager(产 ...

  8. Java编程开发好学吗 怎样才能学好Java编程

    Java编程开发好学吗?怎样才能学好Java编程?很多人都知道Java继承了C语言的特征,入门相对简单,但只有真正学过的人才知道想要学好Java并不容易,因为它涉及很多的知识点,需要遵守很多规则.下面 ...

  9. Java进阶:Set、Map线程安全问题

    文章目录 1. 前言 2. Set 2.1 举例 2.2 源码分析 2.3 解决方案 3. Map 3.1 举例 3.2 异常原因 3.3 解决方案:采用线程安全的Map类 1. 前言 前面的博客已经 ...

最新文章

  1. Mxnet TensorRT
  2. c语言变量在头文件定义变量吗,在头文件C中声明变量
  3. 如何设计真正高性能高并发分布式系统(万字长文)
  4. 2021- 10 -9 LeetCode 958. 二叉树的完全性检验(待补完)
  5. SQL(四) - 子查询和union以及limit分页
  6. 使用Python把PowerPoint文件转换为配乐MP4视频
  7. opencv 图像转换(傅里叶变换)
  8. Vue生命周期---vue工作笔记0013
  9. assert.notDeepEqual()
  10. RedHat Linux 企业5 oracle 10g
  11. 解读Depth Map Prediction from a Single Image using a Multi-Scale Deep Network (2)
  12. 基于qt开发的轻量级浏览器
  13. SAS更新sid的方法,简单有效,sid最新可到2022年3月
  14. 「经济读物」一课经济学
  15. 2020 EBC徒步功课做好 好好工作心态
  16. 《人性的弱点全集》- [美]戴尔·卡耐基/著
  17. HTML文本域添加滑杆,Objective-C 自定义UISlider滑杆 分段样式
  18. PPT文件如何解决不能编辑的问题
  19. MCU简单控制DAC芯片应用(以DAC8550为例)
  20. 树莓派触摸屏翻转显示以及触摸翻转

热门文章

  1. 如何把PDF文档转换成TXT格式文件
  2. 【游戏开发】角色选择功能实现
  3. 【ACMMM 2022】Learning Hierarchical Dynamics with Spatial Adjacency for Image Enhancement
  4. 5.1环绕声是什么意思
  5. sql 经典查询问题
  6. 2019TLC大会精彩回顾—大前端·信息流
  7. ARP欺骗:使用工具:arpspoof、driftnet和ettercap
  8. STM32 gcc编译环境搭建
  9. selenium实现zhilian招聘的爬取
  10. 空间曲线的切线、主法线、副法线