[笔记] 疯狂JAVA讲义(第3版)第8章 Java集合(二)

简介: [笔记] 疯狂JAVA讲义(第3版)第8章 Java集合(二)

[笔记] 疯狂JAVA讲义(第3版)第8章 Java集合(一):https://developer.aliyun.com/article/1537901

8.4.2 ArrayList和Vector实现类


List的两个实现类。ArrayList和Vector都是基于数组实现的List类,封装了一个动态、可再分配的Object[] 数组。


允许使用initialCapacity参数设置数组长度,当元素超出该长度时,initalCapacity会自动增加。


通常无需关系initalCapacity,但如果要添加大量元素时,可以使用ensureCapacity(int minCapacity)一次性增加(到)initalCapacity。可以减少分配次数,提高性能。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46jLwn8w-1588248416674)(media/image6.png)]{width=“7.544671916010499in” height=“1.2098359580052493in”}


ArrayList和Vector用法上几乎完全相同,但Vector是一个古老的集合,里面有一些方法名很长的方法。


除此之外,ArrayList是线程不安全的。


Vector还提供一个Stack子类,模拟栈。由于Vector太古老了,不推荐使用Vector类。


8.4.3 固定长度的List


Arrays.asList(Object… a),将一个数组或指个数的对象转换成一个List集合,该集合是Arrays的内部类ArrayList的实例。


Arrays.ArrayList是一个固定长度的List集合,程序只能遍历集合元素,不可增减。


package ch8;
import java.util.Arrays;
import java.util.List;
public class FixedSizeList {
public static void main(String[] args) {
List fixedList = Arrays.asList(“fk java”,“java EE”);
System.out.println(fixedList.getClass());
fixedList.forEach(System.out::println);
}
}

8.5 Queue集合


Queue用于模拟队列。队列是先进先出(FIFO)的容器。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxVKZt0b-1588248416675)(media/image7.png)]{width=“7.628687664041995in” height=“1.873565179352581in”}


8.5.1 PriorityQueue


Queue的比较标准的实现类。但PriorityQueue保存元素的顺序是按照元素的大小排序的。


因此,并不是按照FIFO原则。


package ch8;
import java.util.PriorityQueue;
public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue pq = new PriorityQueue();
pq.offer(6);
pq.offer(-3);
pq.offer(20);
pq.offer(18);


System.out.println(pq); //输出[-3,6,20,18],受到toString()的影响,实际上调用poll()是按从小到大排序的。


System.out.println(pq.poll());
System.out.println(pq.poll());
System.out.println(pq.poll());
System.out.println(pq.poll());
}
}

PriorityQueue的排序方式和TreeSet基本一致。


8.5.2 Deque接口和ArrayDeque实现类


Deque是一个双端序列。允许从两端操作数据。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwrZi1Er-1588248416675)(media/image8.png)]{width=“7.922744969378828in” height=“4.923360673665792in”}


Deque接口提供了一个典型的实现类:ArrayDeque,可以用来实现Stack和Queue。


package ch8;
import java.util.ArrayDeque;
public class ArrayDequeueStack {
public static void main(String[] args) {
ArrayDeque stack = new ArrayDeque();
stack.push(“java”);
stack.push(“javase”);
stack.push(“Android”);
System.out.println(stack);
System.out.println(stack.peek());
System.out.println(stack);
System.out.println(stack.pop());
System.out.println(stack);
}
}
package ch8;
import java.util.ArrayDeque;
public class ArrayDequeQueue {
public static void main(String[] args) {
ArrayDeque queue = new ArrayDeque();
queue.offer(“java”);
queue.offer(“javaee”);
queue.offer(“Android”);
System.out.println(queue);
System.out.println(queue.peek());
System.out.println(queue);
System.out.println(queue.poll());
System.out.println(queue);
}
}


8.5.3 LinkedList实现类


List的实现类,此外,LinkedList还实现了Deque接口。


package ch8;
import java.util.LinkedList;
public class LinkedListTest {
public static void main(String[] args) {
LinkedList books = new LinkedList();
books.offer(“java”);
books.push(“javaee”);
books.offerFirst(“Android”);
for(int i = 0 ; i < books.size() ; i++) {
System.out.println(books.get(i));
}
System.out.println(books.peekFirst());
System.out.println(books.peekLast());
System.out.println(books.pop());
System.out.println(books);
System.out.println(books.pollLast());
System.out.println(books);
}
}


8.5.4 各种线性表的性能分析


List:线性表接口


ArrayList、LinkedList 两种实现


Queue:队列


Deque:双端队列


一般来说,ArrayList随机访问性能好,LinkedList插入删除时性能好。总体来说,ArrayList性能更好。


List使用使用建议:


遍历:对于ArrayList,使用随机访问 get()方法来遍历;而LinkedList,使用迭代器(Iterator)遍历


线程安全:多线程时,考虑使用Collection将集合包装成线程安全的集合。


8.6 Java 8 增强的Map集合


Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组保存Key,另一组保存Value。


key和value都可以是任何类型的数据,key不能重复。


key -value一一对应。


@key集存储方式和Set存储形式完全相同。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PWWffom-1588248416677)(media/image9.png)]{width=“9.317416885389326in” height=“6.998565179352581in”}


package ch8;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map map = new HashMap();
//放入key-value对,value可以重复,如果放入重复的key,新的value值会覆盖原来的value
map.put(“疯狂Java讲义”,109);
map.put(“疯狂IOS讲义”,10);
System.out.println(map);
//判断是否包含指定key
System.out.println(“包含值 疯狂IOS讲义的key:”+map.containsKey(“疯狂IOS讲义”));
//判断是否包含指定value
System.out.println(“包含值为99的value:”+map.containsValue(10));
//获取key集合,通过遍历key遍历key-value对
for(Object key : map.keySet()) {
System.out.println(key+"–>"+map.get(key));
}
map.remove(“疯狂IOS讲义”);//根据key来删除key-value对
System.out.println(map);
}
}

8.6.1 java8为Map新增的方法


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ngbFHAIz-1588248416679)(media/image10.png)]{width=“8.065573053368329in” height=“7.191802274715661in”}


package ch8;
import java.util.HashMap;
import java.util.Map;
public class MapTest2 {
public static void main(String[] args) {
Map map = new HashMap();
//放入key-value对
map.put(“疯狂java”,109);
map.put(“疯狂IOS”, 99);
map.put(“疯狂Ajex”, 79);
map.replace(“疯狂XML”, 66); //替换key为"疯狂XML"的value。但由于原map没有此key,所以不会替换。也不会新加键值对
System.out.println(map);
//覆盖原value, 变成oldV + 10
map.merge(“疯狂IOS”, 10,
(oldV,param)->(Integer)oldV + (Integer)param);
System.out.println(map);
//当key为java对应的value为null或不存在时,使用计算的结果作为新value
map.computeIfAbsent(“java”, (key)->((String)key).length());
System.out.println(map);
//key对应value存在时,计算新value
map.computeIfPresent(“java”, (key,value)->(Integer)value*(Integer)value);
System.out.println(map);
}
}


8.6.2 java 8改进的HashMap和Hashtable实现类


Hashtable是一个古老的Map实现类,不推荐使用。


为了能够在HashMap中存储对象,作为key的对象必须实现hashCode()和equals()方法。


8.6.3 LinkedMap实现类


使用双向链表维护key的次序。


package ch8;
import java.util.LinkedHashMap;
public class LinkedHashMapTest {
public static void main(String[] args) {
LinkedHashMap scores = new LinkedHashMap();
scores.put(“语文”,90);
scores.put(“数学”,92);
scores.put(“英语”,80);
scores.forEach((key,value)->System.out.println(key+"–>"+value));
}
}


8.6.4 使用Properties读取属性文件


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qyuatnOx-1588248416681)(media/image11.png)]{width=“8.073975284339458in” height=“4.318442694663167in”}


package ch8;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args)throws Exception {
Properties props = new Properties();
//添加属性
props.setProperty(“username”, “yuke”);
props.setProperty(“password”, “123456”);
//保存至a.ini文件
props.store(new FileOutputStream(“a.ini”),“comment line”);
Properties p2 = new Properties();
p2.setProperty(“gender”, “male”);
//将a.ini中key-value追加到p2中
p2.load(new FileInputStream(“a.ini”));
System.out.println(p2);
}
}

8.6.5 SortedMap接口和TreeMap实现类。


TreeMap存储key-value时,根据key进行排序,保证有序。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7B5lp8Qi-1588248416681)(media/image12.png)]{width=“8.157991032370953in” height=“7.8471303587051615in”}


8.6.6 WeakHashMap实现类


类似HashMap,但WeakHashMap只保留对实际对象的弱引用,对象在垃圾回收时可能会被回收。


8.6.7 IdentityHashMap实现类


类似HashMap,但处理相等的key时,仅在key1==key2严格相等时,才认为相等。而HashMap只判断equals()和hashCode()方法。


8.6.8 EnumMap实现类


创建EnumMap时必须指定一个枚举类。


8.6.9 各Map实现类的性能分析


对于一般场景,应该考虑使用HashMap.


如果需要排序,则可以考虑TreeMap。


8.7 HashSet和HashMap的性能选项


HashSet类采用hash算法决定元素存储位置,并通过hash算法来控制集合的大小;


hash表里可以存储元素的位置称为"桶(bucket)",通常情况下,单个"桶"存放一个元素,此时有最好的性能。


hash算法根据hashCode值计算出"桶"的位置,接着从"桶"中取出元素。


但发生hash冲突时,单个桶会存储多个元素,这些元素以链表形式存储,必须按顺序搜索。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XLY8aPY-1588248416682)(media/image13.png)]{width=“3.1758191163604548in” height=“1.6887292213473315in”}


HashSet、HashMap的hash表中都包含如下属性:


容量(capacity):桶数量


初始化容量(initial capacity):


尺寸(size):当前数量


负载因子(load factor):负载因子等于size/capacity,负载因子=0,代表空,负载因子=0.5,代表半满。


负载极限:0~1,当负载因子达到负载极限时,hash表会自动成倍增加容量。默认值0.75.


8.8 操作集合类的工具类:Collections


Collections类提供对集合元素排序、查询、修改等操作。


8.8.1 排序操作


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x0VXM5RJ-1588248416683)(media/image14.png)]{width=“7.586679790026246in” height=“2.1424179790026248in”}


package ch8;
import java.util.ArrayList;
import java.util.Collections;
public class SortTest {
public static void main(String[] args) {
ArrayList nums = new ArrayList();
nums.add(2);
nums.add(-5);
nums.add(3);
nums.add(0);
System.out.println(nums);
Collections.reverse(nums);//翻转
System.out.println(nums);
Collections.sort(nums);//排序
System.out.println(nums);
Collections.shuffle(nums);//随机顺序
System.out.println(nums);
}
}


8.8.2 查找、替换操作


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gs5PfYPQ-1588248416684)(media/image15.png)]{width=“7.947950568678915in” height=“3.94876968503937in”}


package ch8;
import java.util.ArrayList;
import java.util.Collections;
public class SearchTest {
public static void main(String[] args) {
ArrayList nums = new ArrayList();
nums.add(2);
nums.add(-5);
nums.add(3);
nums.add(0);
System.out.println(nums);
System.out.println(Collections.max(nums));
System.out.println(Collections.min(nums));
Collections.replaceAll(nums, 0, 1);//替换
System.out.println(nums);
System.out.println(Collections.frequency(nums, -5));
Collections.sort(nums);//排序
System.out.println(nums);
System.out.println(Collections.binarySearch(nums, 3));//二分查找,要求是排序好的
}
}


8.8.3 同步控制


Collections类提供多个synchronizedXxx()方法,可以将指定集合包装成线程同步的集合。


如:


List list = Collections.synchronizedList(new ArrayList());


8.8.4 设置不可变集合


Collections类提供三类方法来返回一个不可变的集合:


emptyXxx(): 返回一个不可变的Xxx


singletonXxx():返回一个只包含指定对象的xx


unmodifiableXxx():返回指定对象的不可变视图。


package ch8;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class UnmodifiableTest {
public static void main(String[] args) {
List unmodifiableList = Collections.emptyList();
Set unmodifiableSet = Collections.singleton(“疯狂Java讲义”);
Map scores = new HashMap();
scores.put(“语文”,100);
scores.put(“数学”,99);
Map unmodifiableMap = Collections.unmodifiableMap(scores);
}
}


8.9 繁琐的接口:Enumeration 很古老,建议略过,当然我只是建议


//小结,Java集合,内容很多,很难记住每个类的细节,看完书后要做一下精简版的总结。


相关文章
|
7月前
|
Java 大数据 API
Java Stream API:现代集合处理与函数式编程
Java Stream API:现代集合处理与函数式编程
357 100
|
7月前
|
Java API 数据处理
Java Stream API:现代集合处理新方式
Java Stream API:现代集合处理新方式
362 101
|
7月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
6月前
|
存储 算法 安全
Java集合框架:理解类型多样性与限制
总之,在 Java 题材中正确地应对多样化与约束条件要求开发人员深入理解面向对象原则、范式编程思想以及JVM工作机理等核心知识点。通过精心设计与周密规划能够有效地利用 Java 高级特征打造出既健壮又灵活易维护系统软件产品。
168 7
|
8月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
778 23
|
7月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
194 4
|
8月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
441 12
|
8月前
|
存储 缓存 安全
Java集合框架(三):Map体系与ConcurrentHashMap
本文深入解析Java中Map接口体系及其实现类,包括HashMap、ConcurrentHashMap等的工作原理与线程安全机制。内容涵盖哈希冲突解决、扩容策略、并发优化,以及不同Map实现的适用场景,助你掌握高并发编程核心技巧。
|
8月前
|
存储 NoSQL Java
Java Stream API:集合操作与并行处理
Stream API 是 Java 8 提供的集合处理工具,通过声明式编程简化数据操作。它支持链式调用、延迟执行和并行处理,能够高效实现过滤、转换、聚合等操作,提升代码可读性和性能。
|
8月前
|
存储 安全 Java
Java集合框架(一):List接口及其实现类剖析
本文深入解析Java中List集合的实现原理,涵盖ArrayList的动态数组机制、LinkedList的链表结构、Vector与Stack的线程安全性及其不推荐使用的原因,对比了不同实现的性能与适用场景,帮助开发者根据实际需求选择合适的List实现。