《Java编程思想》学习笔记9——集合容器高级
1.Arrays.asList()方法产生的List是一个固定长度的数组,只支持不改变长度的操作,任何试图改变其底层数据结构长度的操作(如,增加,删除等操作)都会抛出UnsupportedOperationException异常。
为了使Arrays.asList()方法产生的List集合长度可变,可以将其作为集合容器的构造方法参数,如:
Set set = new HashSet(Arrays.asList(newint[]{1,23}));
或者将其作为Collections.addAll()方法的参数,如:
Collections.addAll(Arrays.asList(new int[]{1,23}));
2.SortedSet是一个对其元素进行排序了的Set,SortedSet接口有以下方法:
返回此Set中元素进行排序的比较器,如果该方法返回null,则默认使用自然排序。
(4).SortedSet subset(fromElement, toElement):
返回此Set中从fromElement(包括)到toElement(不包括)的子Set。
(5).SortedSet headset(toElement):
(6).SortedSet tailSet(fromElement):
返回此Set中元素大于等于fromElement的子Set。
3.SortedMap是一个根据Key排序的Map,SortedMap接口有以下方法:
返回此Map中key进行排序的比较器,如果返回的是null,则该Map的key使用自然排序。
(4).SortedMap subMap(fromKey, toKey):
返回此Map中key从fromKey(包括)到toKey(不包括)的子Map。
(6).SortedMap tailMap(fromKey):
4.HashMap/HashSet等Hash算法集合重写equals方法和hashCode方法:
- Class A{
- int i;
- public A(int i){
- this.i = i;
- }
- Public static void main(String args[]){
- Map map = new HashMap();
- map.put(new A(1), “First”);
- map.put(new A(2), “Second”);
- A a = new A(1);
- boolean b = map.containsKey(a);
- System.out.println(b);
- }
- }
输出的结果是:false。
Map中有Key为A(1)对象,但是却没有找到,这是因为HashMap使用Hash算法根据对象的hashCode值来查找给定的对象,如果没有重写hashCode和equals方法,则对象默认使用Object的hashCode方法,Object默认hashCode方法使用对象的内存地址作为hashCode值。
为了使Hash算法集合存放对象类型数据符合用户的期望,必须重写对象的hashCode和equals方法,其中hashCode方法用于Hash算法的查找,equals方法用于对象比较,Hash算法中还要用到equals方法如下:
因为Hash算法所使用的hashCode可能会产生碰撞(不相等对象的hashCode值相同),当Hash算法产生碰撞时,就需要再次Hash(即再次通过其他方法计算hashCode值),所以一个对象使用Hash算法时,其对应的HashCode值可能不止一个,而是一组,当产生碰撞时就选择另一个hashCode值。当hashCode值产生碰撞时,还必须使用equals方法方法对象是否相等。
注意:由于Hash算法有可能会产生碰撞(不相等的对象hashCode值相同),所以hashCode和equals方法有如下关系:
(1).equals方法相等的对象,hashCode方法值一定相同。
(2).hashCode方法相同的对象,equals不一定相等。
5.创建只读集合容器:
List,Set和Map类型的集合容器都可以通过下面的方法创建为只读,即只可以访问,不能添加,删除和修改。
- static Collection<String> data = new ArrayList<String>();
- data.add(“test”);
- static Map<String, String> m = new HashMap<String, String>();
- m.put(“key”, “value”);
(1).只读集合:
- Collection<String> c = Collections.unmodifiableCollection(new ArrayList<String>(data));
- System.out.println(c); //可以访问
- //c.add(“test2”);只读,不可添加
(2).只读List:
- List<String> list = Collections.unmodifiableList(new ArrayList<String>(data));
- System.out.println(list.get(0)); //可以访问
- //list.remove(0);只读,不可删除
(3).只读Set:
- Set<String> set = Collections.unmodifiableSet(new HashSet<String>(data));
- System.out.println(set.Iterator().next()) //可以访问
- //set.add(“test”);只读,不可添加
(4).只读Map:
- Map<String, String> map = Collections.unmodifiableMap(new HashMap<String, String>(m));
- System.out.println(map.get(“key”)); //可以访问
- //map.put(“key2”, “value2”);只读,不可添加
只读集合容器会在编译时检查操作,如果对只读集合容器进行增删等操作时,将会抛出UnSupportedOperationException异常。
只读集合容器类似于将集合对象访问控制修饰符设置为private,不同之处在于,其他类可以访问,只是不能修改。
6.线程同步集合容器:
Java集合容器中,Vector,HashTable等比较古老的集合容器是线程安全的,即处理了多线程同步问题。
而Java2之后对Vector和HashTable的替代类ArrayList,HashSet,HashMap等一些常用的集合容器都是非线程安全的,即没有进行多线程同步处理。
Java中可以通过以下方法方便地将非线程安全的集合容器进行多线程同步:
(1).线程同步集合:
Collection<String> c= Collections.synchronizedCollection(newArrayList<String>());
(2).线程同步List:
List<String> c= Collections.synchronizedList(newArrayList<String>());
(3).线程同步Set:
Set<String> c= Collections.synchronizedSet(newHashSet<String>());
(4).线程同步Map:
Map<String> c= Collections.synchronizedMap(newHashMap<String, String>());
7.对象的强引用、软引用、弱引用和虚引用:
JDK1.2以前版本中,只存在一种引用——正常引用,即对象强引用,如果一个对象被一个引用变量所指向,则该对象是可触及(reached)的状态,JVM垃圾回收器不会回收它,弱一个对象不被任何引用变量指向,则该对象就处于不可触及的状态,垃圾回收器就会回收它。
从JDK1.2版本之后,为了更灵活的控制对象生命周期,引入了四种引用:强引用(java.lang.ref.Reference)、软引用(java.lang.ref.SoftReference)、弱引用(java.lang.ref.WeakReference)和虚引用(java.lang.ref.PhantomReference):
(1). 强引用(java.lang.ref.Reference):
即Java程序中普遍使用的正常对象引用,存放在内存中得对象引用栈中,如果一个对象被强引用,则说明程序还在使用它,垃圾回收器不会回收,当内存不足时,JVM抛出内存溢出异常使程序异常终止。
(2). 软引用(java.lang.ref.SoftReference):
如果一个对象只具有软引用,则内存空间足够,垃圾回收器也不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,JVM就会把这个软引用加入到与之关联的引用队列中。
(3). 弱引用(java.lang.ref.WeakReference):
弱引用用来实现内存中对象的标准映射,即为了节约内存,对象的实例可以在一个程序内多处使用。
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的后台线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
(4). 虚引用(java.lang.ref.PhantomReference):
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
JVM中,对象的引用往往都是很复杂的,各个对象之间相互引用形成一个内存引用树,java中某个对象是否可触及,有以下两条判断原则:
a.单条引用路径可及性判断:在这条路径中,最弱的一个引用决定对象的可及性。
b.多条引用路径可及性判断:几条路径中,最强的一条的引用决定对象的可及性。
软引用,弱引用,虚引用例子如下:
- package com.test.reference;
- //测试对象
- class VeryBig {
- private static final int SIZE = 10000;
- private long[] la = new long[SIZE];
- private String ident;
- public VeryBig(String id) {
- ident = id;
- }
- public String toString() {
- return ident;
- }
- protected void finalize() {
- System.out.println("Finalizing " + ident);
- }
- }
- package com.test.reference;
- import java.lang.ref.PhantomReference;
- import java.lang.ref.Reference;
- import java.lang.ref.ReferenceQueue;
- import java.lang.ref.SoftReference;
- import java.lang.ref.WeakReference;
- import java.util.LinkedList;
- public class TestReferences {
- //引用队列
- private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
- //检查引用队列是否为空
- public static void checkQueue() {
- //强引用,轮询引用队列,看是否有可以的对象引用
- Reference<? extends VeryBig> inq = rq.poll();
- if (inq != null)
- //如果有可以使用的对象引用,则打印出该引用指向的对象
- System.out.println("In queue: " + inq.get());
- }
- public static void main(String[] args) {
- int size = 2;
- //创建存放VeryBig对象的软引用集合
- LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>();
- for (int i = 0; i < size; i++) {
- //将对象和软引用添加到引用队列中
- sa.add(new SoftReference<VeryBig>(new VeryBig("Soft " + i), rq));
- System.out.println("Just created: " + sa.getLast());
- checkQueue();
- }
- //创建存放VeryBig对象的弱引用集合
- LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>();
- for (int i = 0; i < size; i++) {
- //将对象和弱引用添加到引用队列中
- wa.add(new WeakReference<VeryBig>(new VeryBig("Weak " + i), rq));
- System.out.println("Just created: " + wa.getLast());
- checkQueue();
- }
- SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig(
- "Soft"));
- WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig(
- "Weak"));
- //垃圾回收器回收,在回收之前调用对象的finalize()方法
- System.gc();
- //创建存放VeryBig对象的虚引用集合
- LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<PhantomReference<VeryBig>>();
- for (int i = 0; i < size; i++) {
- //将对象和虚引用添加到引用队列中
- pa.add(new PhantomReference<VeryBig>(new VeryBig("Phantom " + i),
- rq));
- System.out.println("Just created: " + pa.getLast());
- checkQueue();
- }
- }
- }
输出结果为:
Just created:java.lang.ref.SoftReference@757aef
Just created:java.lang.ref.SoftReference@d9f9c3
Just created:java.lang.ref.WeakReference@9cab16
Just created:java.lang.ref.WeakReference@1a46e30
In queue: null
Finalizing Weak 0
Finalizing Weak
Finalizing Weak 1
Just created:java.lang.ref.PhantomReference@3e25a5
In queue: null
Just created:java.lang.ref.PhantomReference@19821f
注意:由于System.gc()只是通知JVM虚拟机可以进行垃圾回收器可以进行垃圾回收了,但是垃圾回收器具体什么时候允许说不清楚,所以这个输出结果只是个参考,每次运行的结果Finalize方法的执行顺序不太一样。
从程序可以看出,尽管对象被引用,垃圾回收器还是回收了被引用对象,引用队列总是创建一个包含null对象的引用。
8.WeakHashMap:
WeakHashMap专门用于存放弱引用,WeakHashMap很容易实现弱引用对象标准映射功能。
在WeakHashMap中,只存储一份对象的实例及其值,当程序需要对象实例值时,WeakHashMap从现有的映射中找出已存在的对象值映射。
由于弱引用节约内存的技术,WeakHashMap允许垃圾回收器自动清除器存放的key和value。WeakHashMap自动将其中存放的key和value包装为弱引用,当key不再被使用时,垃圾回收器自动回收该key和value。
《Java编程思想》学习笔记9——集合容器高级相关推荐
- Java编程思想学习笔记-第11章
<?xml version="1.0" encoding="utf-8"?> Java编程思想学习笔记-第11章 Java编程思想学习笔记-第11章 ...
- Java编程思想学习笔记4 - 序列化技术
今天来学习下Java序列化和反序列化技术,笔者对<Java编程思想>中的内容,结合网上各位前辈的帖子进行了整理和补充,包括: 序列化概述 Java原生序列化技术 Hessian序列化技术 ...
- JAVA编程思想学习笔记——第一章 对象导论
搞了一年多java,野路子出身,发现java基础这块还是相当的薄弱!故决定学习<Java编程思想>这本书.在此把学习的知识点记录下! 面向对象的五大特性 1.万物皆为对象 2.程序是对象的 ...
- Java编程思想 学习笔记1
一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...
- Java编程思想 学习笔记7
七.复用类 1.组合语法 在新的类中产生现有类的对象.由于新的类是由现有类的对象所组成,所以这种方法叫做组合. 类中域为基本类型时能够自动被初始化为零.对象引用被初始化为null. 编译器不是简单地为 ...
- java编程思想 学习笔记(2)
第二章 一切都是对象 用引用(reference)操纵对象 String s = "asdf"; String s; 但这里所创建的只是引用,并不是对象.如果此时向s 发送 ...
- java编程思想学习笔记(第七章:复用类)
复用代码是java众多引人注目的功能之一.但是要想成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,它还必须能够做更多的事情. 7.1组合语法 将对象引用置于新类中.每一个非基本类型的对象 ...
- 01.Java 编程入门学习笔记20210307
Java 编程入门学习笔记-day01 第0章:编程入门 1.计算机的概述 计算机 = 硬件 + 软件 1.1硬件:冯诺依曼体系 CPU: CPU的衡量标准:速度的计量单位是赫兹(Hz),1Hz相当于 ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
最新文章
- ViewBag、ViewData和TempData使用方法、区别与联系
- WPF WindowStyle为None
- scikit-learn一般实例之一:绘制交叉验证预测
- mxnet基础到提高(35)-ndarray
- 后台通过request.setAttribute向前台传值,前台如何去获取其中的对象或属性值
- Python入门基础篇(二)元组,更适合新手哦!!!
- iview vue 打包图标不显示_VueCLI3.0干货系列之集成iview
- 红旗Linux职称考试模块,计算机职称考试红旗Linux Desktop 6.0考试大纲
- 关系型数据库一致性的理解
- 深入浅出 NXLog (一)
- gms认证流程_GMS测试认证的具体操作流程
- [精简]托福核心词汇78
- word2vec训练维基百科中文词向量
- ‘gbk‘ codec can‘t decode byte 0xae in position 199: illegal multibyte sequen 问题解决
- windows核心编程之 C/C++运行库注意事项
- linux由浅入深学习一
- java共享文件夹SMB1服务报错jcifs.smb.SmbException: Failed to connect: 0.0.0.0<00>/122.168.23.26
- Android通过Canvas手绘一个折线图
- Kubernetes 概述和搭建 (多节点)
- Component Object Model (COM)
热门文章
- 【OpenGL】二十四、OpenGL 纹理贴图 ( 读取文件内容 | 桌面程序添加控制台窗口 | ‘fopen‘: This function may be unsafe 错误处理 )
- 【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )
- 【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )
- itchat 动态注册
- 云计算之路-试用Azure:数据库备份压缩文件在虚拟机上的恢复速度测试
- gcc 常用命令(逐渐完善)
- 满有趣的屏幕快捷键;)
- JVM自动化的内存分配与内存回收
- CentOS启动不显示图形界面直接进入命令行模式
- 性能优化技巧 - 组表数据更新