Java高级—集合

首先建议看一下前一章的集合框架
从这一章开始,我们正式进入Java高级技术部分

集合:Collection 无序可重复

文章目录

  • Java高级---集合
    • 一、List :有序,可重复
    • 二、Set :无序,不可重复
    • 三、Map:键值对
      • Map怎么通过Value进行比较呢?

一、List :有序,可重复

1、ArrayList:一维数组作为底层存储
特点:遍历、随机访问快、修改方便,其他慢

 这里讲一下插入方法:add(Obj)和add(1,Obj)插入数据元素的底层实现原理:【这里建议看Java源码】插入前判断容量是否越界,如果越界,则扩容。扩容后比数组最大长度大,则是int最大值没有达到数组最大长度,就是数组最大长度正常情况:扩容1.5倍,如果不够,则直接把当前长度赋值给数组新长度如果是新数组,与10比较,比10大,大的直接赋值给数组长度不需要扩容或扩容完成则直接插入

那接下来,我们看一下ArrayList如何使用:
1.插入

ArrayList a = new ArrayList();//声明并分配空间//元素的插入
a.add("abc");
a.add("123");
a.add("唯颂科技");
a.add("2s留#%");
a.add("abc");
a.add(1,"shall");     //指定位置插入,元素后移System.out.println(a);//因为重写了toString方法,所以可以直接输出

结果显示

2.删除

 if(a.contains("123")) {a.remove("123");//删除对象}a.remove(1);//删除指定下标元素,下标从0开始

两种方式删除都可以,如果list中没有你要删除的元素,你删除了也不会报错

3.查找

a.get(2);        //只有根据下标指定查找元素一个查询方法

4.修改

a.set(1,"溜溜球");    //指定位置修改

5.输出(常见的三种输出方式)

//1.普通for
for (int i = 0; i < a.size(); i++) {System.out.println(a.get(i));//获取当前元素
}
//2.增强for
for(Object s:a){    //由于上面一开始没有定义类型,所以这里写了ObjectSystem.out.println(s);
}
//3.迭代器
Iterator it = a.iterator();
while (it.hasNext()){System.out.println(it.next());//一次循环只能使用一次next(),不然会出错//如果要用多次,赋值给变量即可
}

ArrayList常用方法

2、LinkedList:以链表作为底层存储
特点:增加、删除快,其他慢
其实有点数据结构基础的都知道这二者的特点

LinkedList中的方法和ArrayList几乎一样,只不过多一些头结点、尾节点的操作方法
那些一样的我就不写了,这里主要讲一下没有的:

然后:
push:在头结点处插入元素

//jdk1.8源码public void push(E e) {addFirst(e);}

pop:删除头结点

//jdk1.8源码
public E pop() {return removeFirst();}

peek:返回头结点

//jdk1.8源码
public E peek() {final Node<E> f = first;return (f == null) ? null : f.item;}/*** Retrieves, but does not remove, the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/

peekFirst:返回头结点
peekLast:返回尾结点

poll:返回头结点,只不过是unlinked

//jdk1.8源码
public E poll() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}/*** Retrieves and removes the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/

pollFirst:返回头结点
pollLast:返回尾结点

offer:插入元素

//jdk1.8源码
public boolean offer(E e) {return add(e);   //其实就是插入}

offerFirst:在头结点插入元素
offerLast:在尾结点插入元素

是不是感觉LinkedList里面一堆功能重复的方法

3、Vector:ArrayList的线程安全版本
由于使用比较少,所以在这里就不赘述了
------------------------------------------------------------------------------------------------------
最后,做个小小的练习:
Book类

/* 定义图书类Book,具有属性账号id,书名name、作者author 和价格price,* 在创建图书对象时要求通过构造器进行创建,一次性将四个属性全部赋值,* 1)要求账户属性是int型,名称是String型,作者是String型,价格是double,* 请合理进行封装。* 2)在Book类,添加toString方法,要求返回 图书信息字符串,使用\t隔开各信息* 3)要求定义一个图书馆Library类,在图书馆类中添加一个集合用于保存多本图书* 4)在图书馆类中要求能够新增图书* 5)在图书馆类中要求可以查看所有添加过的图书* 6)不允许添加重复的图书(如果账号id和书名name相同,则认为两本书是相同的)* (重写equals方法)*/
public class Book {private int id;private String name;private String author;private double price;public Book(int id, String name, String author, double price) {this.id = id;this.name = name;this.author = author;this.price = price;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book{" +"书籍编号=" + id +"\t"+"书籍名称=" + name + "\t"+"书籍作者=" + author + "\t" +"书籍价格=" + price +'}'+"\n";}public boolean equals(Book b){if(null==this.name||0>=this.id||b.getId()<=0||null==b.getName()){return false;}return this.name.equals(b.getName())&&this.id==b.getId();}
}

Library类

public class Library {public static void main(String[] args) {List<Book> list = new ArrayList();Scanner sc = new Scanner(System.in);String s = "";do{System.out.println("需要添加书籍吗?(y/n)");s = sc.next();if("y".equals(s)){System.out.println("请输入图书编号:");int id = sc.nextInt();System.out.println("请输入图书名称:");String name = sc.next();System.out.println("请输入图书作者:");String author = sc.next();System.out.println("请输入图书价格:");double price = sc.nextDouble();Book temp = new Book(id,name,author,price);if(list.size()==0){     //为空时,直接插入list.add(temp);}int flag = 1;for (int i = 0; i < list.size(); i++) {if(!list.get(i).equals(temp)) {//不同flag = 2;}else {flag = 1;break;} //相同}if(flag==2)list.add(temp);}elsebreak;}while ("y".equals(s));System.out.println(list);}
}

结果显示

二、Set :无序,不可重复

1、HashSet:是以HashMap的key值的Hash码来进行存储(保证唯一,理论上)
Set中的方法和List几乎一样,所以就不写了。这里就看一次add方法
可以点进Set的add方法看一看

具体使用

HashSet hashSet = new HashSet();    //先不使用泛型
hashSet.add("abc");
hashSet.add(123);
hashSet.add("123");
hashSet.add("123");                   //add源码是使用equals进行比较,只输出一个
hashSet.add(new String("123"));
System.out.println(hashSet);
hashSet.remove("123");
System.out.println(hashSet);
Iterator it = hashSet.iterator();   //这里不能是用fori形式,可以foreach,因为set没有下标
while (it.hasNext()){System.out.println(it.next());
}
ArrayList al = new ArrayList();
al.addAll(hashSet);//把set扔到list中

结果显示

2、TreeSet是一个有序的集合,它的作用是提供有序的Set集合。它继承了AbstractSet抽象类,实现了NavigableSet,Cloneable,Serializable接口。TreeSet是基于TreeMap实现的,TreeSet的元素支持2种排序方式:自然排序或者根据提供的Comparator进行排序

TreeSet的底层实际使用的存储容器就是TreeMap。对于TreeMap而言,它采用一种被称为”红黑树”的排序二叉树来保存Map中每个Entry。每个Entry被当成”红黑树”的一个节点来对待。

这里使用就和上面的HashSet一样,所以就不写了。

三、Map:键值对

key不能重复,value可以。
包含接口Entry<K,V>
在HashMap中使用Node结点实现Entry键值对
Node结点用next属性实现单链表

Map底层:数组+单向链表,1.8之后加入红黑树【红黑树是一种自平衡二叉树,通过左旋和右旋进行平衡】

数组+链表—>红黑树 的条件
一个是链表的长度达到8个,一个是数组的长度达到64个,转用红黑树进行底层存储


为什么是节点数到8个就转成红黑树?
官方解释:理想情况下使用随机的哈希码,容器中节点分布在hash桶中的频率遵循泊松分布,按照泊松分布的计算公式计算出了桶中元素个数和概率的对照表,可以看到链表中元素个数为8时的概率已经非常小,再多的就更少了,所以原作者在选择链表元素个数时选择了8,是根据概率统计而选择的

【Tips:泊松分布】
参考链接:http://www.math.wm.edu/~leemis/2008amstat.pdf
参考链接:https://mp.weixin.qq.com/s/IurrCgtO6ggmfby3oDByng

泊松分布(Poisson)、二项式分布都属于 离散分布
正态分布(Normal)属于 连续分布

二项式分布,样本无穷大—>泊松分布,样本无穷大—>正态分布

为什么使用红黑树
因为不仅查询速度快,虽然不及平衡二叉树,但是也没差多少,相反,插入删除的效率却大大优于平衡二叉树

Map中HashMap(不安全,会死循环,但是快)最为典型,至于什么HashTable(线程安全,但是慢),concurrentHashMap【分段锁,解决二者问题】等这里不重点讲了。

HashMap
默认容量:16,负载因子:0.75
首先是方法,和List几乎一样,只不过插入和修改不同,在Map中插入和修改都是put,put相同key的时候,value就会覆盖,原来内容会因为失去指向而在内存当中,等待Java垃圾回收机制清理。

具体可以看下面代码:

public class TestHashMap {public static void main(String[] args) {HashMap<Integer,String> map = new HashMap(); //注意泛型,这里写不写无所谓map.put(1,"zxx");        //增加:key-valuemap.put(3,"Jad");map.put(3,"厉害的感觉");  //修改:一个key只能有一个valuemap.replace(1,"Lif");    //修改,本质还是put,可以进去看源码map.remove(2);      //删除map.remove(2,"dg");System.out.println(map.get(3));                //输出System.out.println(map);//4种遍历Iterator it = map.entrySet().iterator();      //键值对:entrySetwhile (it.hasNext()){System.out.println(it.next());}Iterator iter = map.keySet().iterator();      //keywhile (iter.hasNext()){System.out.println(iter.next());}Iterator iters = map.values().iterator();     //valuewhile (iters.hasNext()){System.out.println(iters.next());}map.forEach((key,value)->{                    //lamba表达式System.out.println(key);System.out.println(value);});}
}

【注意:keySet返回的是Set类型,value返回的是Collection类型】

Map常用方法

举个例子:
要求:
学员应聘至外企工作,每个学员都会有一个英文名称,对应该学员对象。请实现通过英文名称,获得该学员对象的详细信息
学员属性包括姓名、性别、成绩

学生类:

public class Student  implements Comparable<Student>{private String name;private String gender;private int score;public Student(String name, String gender) {this.name = name;this.gender = gender;}public Student(String name, String gender, int score) {this.name = name;this.gender = gender;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public double getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return  "姓名:" + name + "\t" +"性别:" + gender + "\t"+"成绩:" + score ;}
}

测试类:

public class TestStudent {public static void main(String[] args) {Student s1 = new Student("Jack","男",98);Student s2 = new Student("Alis","女",87);Student s3 = new Student("Louis","女",59);Student s4 = new Student("Tom","男",88);HashMap<String,Student> map = new HashMap();map.put("杰克",s1);map.put("爱丽丝",s2);map.put("路易斯",s3);map.put("汤姆",s4);//2中输出方式
//        Collection c = map.values();
//        for(Object s: c){
//            System.out.println(s);
//        }//        Scanner sc  = new Scanner(System.in);     //按输入进行输出
//        System.out.println("请输入名称");
//        String name = sc.next();
//        if(map.containsKey(name)) {
//            System.out.println(name+map.get(name).toString());
//        }else {
//            System.out.println("抱歉没有这个人");
//        }}
}

Map怎么通过Value进行比较呢?

通过转成其他类型的集合,例如转成List,自定义比较器,利用Collections.sort(List,Comparator)进行排序

/*** @Author shall潇* @Date 2021/1/29* @Description     由于Collections类只给list,set用,Map不能直接用,所以得转成list*/
public class MapValueSort {public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();//插入数据map.put("zzz",23);map.put("Tom",53);map.put("Jack",63);map.put("Luis",27);map.put("Shall",34);//自定义比较规则Comparator<Map.Entry<String,Integer>> comparator = new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {return o1.getValue()-o2.getValue();   //年龄升序}};//放入ListList<Map.Entry<String,Integer>> list = new LinkedList(map.entrySet());Collections.sort(list,comparator);  //两个参数:list集合,比较器对象//输出for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i).getKey()+" = "+list.get(i).getValue()+"\t");}}
}

结果显示

Java高级---集合相关推荐

  1. Educoder–Java高级特性(第二章)- 集合框架【笔记+参考代码】

    Educoder–Java高级特性(第二章)- 集合框架[笔记+参考代码] 第一关 编程要求 请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,创建ArrayList集 ...

  2. Java高级面试-超级全面-大厂集合

    Java研发工程师知识点总结 大纲 一.Java基础(语言.集合框架.OOP.设计模式等) 二.Java高级(JavaEE.框架.服务器.工具等) 三.多线程和并发 四.Java虚拟机 五.数据库(S ...

  3. 【Java高级特性】集合框架和泛型(一)

    1.认识集合 Java中可以使用数组存储多个类型相同的数据,但是使用数组存在如下缺陷: 数组长度固定,不能很好的适应元素动态变化的情况: 可以通过数组名.length获取数组的长度,但是不能直接获取数 ...

  4. Java高级----List集合、Set集合、Map集合总结

    文章目录 一.集合的概念 1.集合概念 2.集合中常用的方法 二.Java中集合的分类 1.Collection接口 2.Map接口 3.Collections工具类 三.Collection接口 1 ...

  5. Java高级特性增强-多线程

    请戳GitHub原文: https://github.com/wangzhiwub... 大数据成神之路系列: 请戳GitHub原文: https://github.com/wangzhiwub... ...

  6. java安装_我最喜欢的Java高级开发人员书籍

    java安装 我上一篇博客文章(我对高级Java开发人员的十个最喜欢的在线资源)的想法,是由Xiaoran Wang发表的 "面向高级Java开发人员的十大网站"的启发. Wang ...

  7. java初始化集合_Java 中初始化 List 集合的 6 种方式!

    List 是 Java 开发中经常会使用的集合,你们知道有哪些方式可以初始化一个 List 吗?这其中不缺乏一些坑,今天栈长我给大家一一普及一下. 如果想学习Java工程化.高性能及分布式.深入浅出. ...

  8. 面试 Java 高级后端开发,要准备哪些知识点?

    由于我做了比较长时间的技术面试官,根据我的面试体会,不少同学收到面试后,什么准备也不会做,到时候就来了. 这样做的后果是:不知彼,不知己,每战必殆.哪怕侥幸面试成,工资一定会被压得很低. 其实公司肯花 ...

  9. 2018年一线互联网公司Java高级面试题总结

    1.hashcode相等两个类一定相等吗?equals呢?相反呢? 2.介绍一下集合框架? 3.hashmap hastable 底层实现什么区别?hashtable和concurrenthashta ...

最新文章

  1. 《数学建模:基于R》——2.2 方差分析
  2. 《Spring Cloud Netflix官方文档》2. 服务发现:Eureka服务器
  3. python 读取excel图片_如何用Python读取Excel中图片?
  4. 黑科技绝对不能错过!随机采样方法MCMC
  5. 化工计算机软件基础考试题,化工原理模拟试题(一)及答案.doc
  6. MHA高可用 MHA+Keepalive
  7. MakeDirZ.bat
  8. C#窗体标准计算器(下) 初级新手请多担待。
  9. 阿里云ECS云服务器快照
  10. 苹果8a1660是什么版本_苹果7a1660是什么版本
  11. 【学生个人网页设计作品】使用HMTL制作一个超好看的保护海豚动物网页
  12. 如何理解“安全的本质是信任问题”
  13. 天空卫士API数据安全解决方案
  14. 抖音小店商品如何挂到精选联盟上面?带货有什么技巧方法?
  15. html给用户自定义页面,个人门户增加自定义html模块(重要!)
  16. 简约纯色卡通蝴蝶Mac动态壁纸
  17. ping问题详解(请求超时,无法访问目标主机)
  18. 每日一题 --- P1093 [NOIP2007 普及组] 奖学金[洛谷][JAVA]
  19. 好嗨游戏:20款史上最佳的MMORPG游戏,看看有没有你知道的?
  20. 版本管理工具使用之svn

热门文章

  1. 广州人民优步奖励政策(7月13日~7月19日)
  2. 红外避障模块c语言编写程序,红外避障模块(红外对管)51单片机驱动源程序
  3. 百度地图api周边搜索功能
  4. 除了菊纹识别,AI还有哪些奇奇怪怪的识别能力?
  5. RabbitMQ系列随笔
  6. 关于软件工程----一线城市与二三线城市的区别
  7. 杭州地区IT公司招聘分析与求职建议
  8. python爬虫之字符集和编码
  9. Docker简介与安装
  10. 使用多媒体API枚举音频设备 - zgl7903的专栏 - CSDNBlog