CoreJava 笔记总结-第九章 集合

第九章 集合

文章目录

  • 第九章 集合
    • `Java`集合框架
      • 集合接口与实现分离
      • `Collection`接口
      • 迭代器
      • 泛型实用方法
    • 集合框架中的接口
    • 具体集合
      • 链表
      • 数组列表
      • 散列集
      • 树集
      • 优先队列
    • 映射
      • 映射的基本操作
      • 更新映射条目
      • 映射视图
      • 弱散列试图
      • 链接散列集与映射
      • 枚举集与映射
      • 标识散列映射
    • 视图与包装器
      • 小集合
      • 子范围
      • 不可修改视图
      • 同步视图
    • 算法
      • 为什么使用泛型算法
      • 排序与混排
      • 二分查找
      • 简单算法
      • 批操作
      • 集合和数组的转换
    • 遗留的集合
      • 位集

Java集合框架

集合接口与实现分离

  • 队列,先进先出
  • 队列接口最简形式:
public interface Queue<E>{void add(E element);E remove();int size();
}
  • 队列实现: 1. 使用循环数组 2. 使用链表

  • public class CirclarArrayQueue<E> implements  Queue<E>{private int head;private int tail;CirclarArrayQueue(int capacity);public void add(E element);public E remove();public int size();private E[] element;
    }
    

Collection接口

  • 集合类的基本接口是Collection接口
public interface Collection<E>{boolean add(E element);Iterator<E> iterator();...
}

迭代器

  • Iterator接口包含
public interface Iterator<E>
{E next();boolean hasNext();void remove();default void forEachRemaining(Consumer<? super E> action);
}
  • 访问集合中的元素
Collection<String> c = ...;
Iterator<String> iter = c.iterator();
while(iter.hasNext()){String element = iter.next();...
}或者直接for(String elem: c){...}
  • for-each循环可以处理任何实现了Iterable接口的对象
public interface Iterable<E>{Iterator<E> iterator();
}

Collection接口扩展了Iterable接口,所以标准库中任何集合都有可以使用for-each循环

  • 也可以forEachRemaining(element->do sth. with element)对于迭代器每个元素调用这个lambda表达式直到没有元素为止
  • java迭代器位于两个元素之间,调用next,迭代器越过下一个元素, 并且返回刚刚越过元素的引用
  • Iterator接口的remove方法将删除上次调用next方法返回的元素
Iterator<Stirng> it = c.iterator();
it.next();
it.remove();
//删除该字符串的第一个元素
  • remove方法调用之前没有调用next方法会抛出IllegalStateException异常

泛型实用方法

  • P372

集合框架中的接口

  • 集合中有两个基本接口Collection, Map
  • 在集合中插入元素boolean add(E element); 映射包含键值对,插入用V put(K key, V value);
  • 从映射中读取值V get(K key);
  • List是一个有序集合,可以用迭代器访问,可以随机访问(访问整数索引)
  • Set接口等同于Colletion接口,其add方法不允许增加重复元素, hasCode保证包含相同元素得到相同的散列码,equals相等

具体集合

链表

  • java中, 所有链表实际上都是双向链接的

  • 先添加3个元素, 再将第二个元素删除

    var a = new LinkedList<String>();
    a.add("Amy");
    a.add("Carl");
    a.add("Erica");
    Iterator<Stirng> iter = staff.iterator();
    String first = iter.next();
    String second = iter.next();
    iter.remove();
    
  • 链表和泛型集合之间的区别: 链表是一个有序集合, LinkList.add方法将对象添加到链表尾部

  • 反向遍历链表: LinkIterator接口: E previous(); boolean hasPrevious();

  • 为了避免并发修改异常:可以根据需要为集合关联过多个迭代器,但是迭代器只能读取集合

  • LinkedList类提供了get方法访问某个特定元素,但是效率不高

package chapter9_set.linkedList;import java.util.*;public class LinkedListTest {public static void main(String[] args) {var a = new LinkedList<String>();a.add("Amy");a.add("Carl");a.add("Erica");var b = new LinkedList<String>();b.add("Bob");b.add("Doug");b.add("Frances");b.add("Gloria");//merge the words from b into aListIterator<String> aIter = a.listIterator();Iterator<String> bIter = b.iterator();while (bIter.hasNext()) {if(aIter.hasNext()) aIter.next();aIter.add(bIter.next());}/*for (String s : b) {if (aIter.hasNext()) aIter.next();aIter.add(s);}*/System.out.println(a);//remove every second word from bbIter = b.iterator();while (bIter.hasNext()) {bIter.next();if (bIter.hasNext()) {bIter.next();bIter.remove();}}System.out.println(b);//bulk operation: remove all words in b from aa.removeAll(b);System.out.println(a);}
}
/*
Connected to the target VM, address: '127.0.0.1:54324', transport: 'socket'
[Amy, Bob, Carl, Doug, Erica, Frances, Gloria]
[Bob, Frances]
[Amy, Carl, Doug, Erica, Gloria]
Disconnected from the target VM, address: '127.0.0.1:54324', transport: 'socket'
*/

数组列表

  • ArrayList封装了一个动态再分配的对象数组
  • Vector类创建动态数组,其所有方法都是同步的,如果只是一个线程的话用ArrayList

散列集

  • 散列表用链表数组实现
  • 每个列表被称为桶,计算散列码,与桶的总数取余,得到的结果就是保存这个元素桶的索引
  • 装填因子(一般0.75)确定何时对于这个表进行再散列

树集

  • 树集是一个有序集合
  • 任意顺序插入,但是遍历时,值按照排序过后的方式呈现
package chapter9_set.treeSet;import java.util.*;public class TreeSetTest {public static void main(String[] args) {var parts = new TreeSet<Item>();parts.add(new Item("Toaster", 1234));parts.add(new Item("Widget", 4562));parts.add(new Item("Modem", 9912));System.out.println(parts);var sortByDescription = new TreeSet<Item>(Comparator.comparing(Item::getDescription));sortByDescription.addAll(parts);System.out.println(sortByDescription);}
}package chapter9_set.treeSet;import java.util.*;public class Item implements Comparable<Item>
{private String description;private int partNumber;public Item(String aDescription, int aPartNumber) {description = aDescription;partNumber = aPartNumber;}public String getDescription() {return description;}public String toString() {return "[description = " + description + ", partNumber = " +  partNumber + " ]";}public boolean equals(Object otherObject) {if (this == otherObject) return true;if(otherObject == null) return  false;if(getClass() != otherObject.getClass()) return false;var other = (Item) otherObject;return Objects.equals(description, other.description) && partNumber == other.partNumber;}public int hasCode() {return Objects.hash(description, partNumber);}public int compareTo(Item other) {int diff = Integer.compare(partNumber, other.partNumber);return diff != 0 ? diff : description.compareTo(other.description);}
}

优先队列

  • 优先队列中元素可以按照任意顺序插入,但会按照有序顺序检索
  • 只要调用remove方法,总会获得当前优先队列中最小的元素
  • 优先队列使用堆,其添加和删除操作将最小元素移动到根
  • 这里迭代并没有按照顺序来访问元素,删除操作却总是删除剩余元素中最小的那个
package chapter9_set.priorityQueue_Heap;import java.util.*;
import java.time.*;public class PriorityQueueTest {public static void main(String[] args) {var pq = new PriorityQueue<LocalDate>();pq.add(LocalDate.of(1906, 12, 9));pq.add(LocalDate.of(1806, 12, 9));pq.add(LocalDate.of(1206, 12, 9));pq.add(LocalDate.of(1826, 12, 9));pq.add(LocalDate.of(1826, 2, 9));pq.add(LocalDate.of(1826, 1, 10));System.out.println("Iterating over elements...");for (LocalDate date : pq) {System.out.println(date);}System.out.println("Removing elements...");while (!pq.isEmpty())System.out.println(pq.remove());}
}

映射

  • map映射存放键值对

映射的基本操作

  • HashMao, TreeMap: 散列映射稍快,不需要按照有序顺序访问键选择散列映射
  • 键必须唯一
  • remove删除给定键对应的元素, size方法返回映射中元素数
  • 迭代处理映射的键和值,使用forEach方法
Map<String, Integer>scores = ...;
int score = scores.getOrDeaufault(id, 0);scores.forEach((k. v) -> System.out.println("key" + k + ", value=" + v)); //lambda
package chapter9_set.map;import java.util.HashMap;public class MapTest {public static void main(String[] args) {var staff = new HashMap<String, Employee>();staff.put("123-15-1555", new Employee("Amy Lee"));staff.put("157-58-9999", new Employee("Harry Hacker"));staff.put("154-87-9999", new Employee("Ou Kunnan"));staff.put("548-84-1111", new Employee("Da Bendan"));System.out.println(staff.toString());//System.out.println(staff);staff.remove("123-15-1555");staff.put("999-99-9999", new Employee("Hee"));System.out.println(staff.get("999-99-9999"));staff.forEach((key, value) -> System.out.println("key=" + key + ", values=" + value));}
}package chapter9_set.map;public class Employee {private String name;public Employee(String name) {this.name = name;}public String getName() {return name;}
}

更新映射条目

counts.put(word, counts.get(word) + 1);
//第一次看到word会出现`NullPointerException`counts.put(words, counts.getOrDefault(word, 0) + 1);counts.putIfAbsent(word, 0);
counts.put(word, counts.get(word) + 1);counts.merge(word, 1, Integer::sum);

映射视图

  • 3种视图: 键集, 值集, 键值集

Set keySet();

Collection values();

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

  • 枚举映射条目:

  • for(Map.Entry<String, Employee> entry : staff.entrySet()){//for(var entry : staff.entrySet())String k = entry.getKey();Employee v = entry.getValue();......
    }
    
  • 在键集视图可以调用remove,会删除键值对, 但是不能添加元素(会抛出UnsupportedOperationException)

  • 映射条目集视图也有同样的限制


弱散列试图

  • WeakHashMap使用弱引用保存键
  • P400

链接散列集与映射

  • LinkedHashSet, LinkedHashMap会记住元素插入顺序
var staff = new LinkedHashMap<String, Employee>();
staff.put("153156", new Employee("BJv"));
staff.put("2516256", new Employee("Dv"));
staff.put("5453156", new Employee("AJv"));
staff.put("953156", new Employee("BAJVJv"));var it = staff.keySet().iterator();
while(it.hasNext()){System.out.println(it.next());
}
//        staff.values().iterator()
  • 最近最少使用原则: 访问频率高的放在内存种,访问频率低的放在数据库
var cache = new LinkedHashMap<K, V>(128, 0.75F, true){protected boolean removeEldestEntry(Map.Entry<K, V> eldest){return size() > 100;}
}

枚举集与映射

  • EnumSet没有公共构造器,使用静态工厂方法构造这个集:
enum Weekday{MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};
EnumSet<Weekday> a = EnumSet.allOf(Weekday.class);
...
  • EnumMap是一个键类型为枚举类型的映射
var a = new EnumMap<Weekday, Employee>(Weekday.class);

标识散列映射

  • IdenetityHashMap: 键值不是使用函数hadCode, 而是方法System.identityHashCode
  • 根据内存地址计算散列码
  • 两个对象进行比较时,使用==, 而不使用equals

视图与包装器

  • keySet方法返回了一个实现了Set接口的类对象,由这个类的方法操纵原映射.这种集合称为视图
  • 视图: 根据用户观点所定义的数据结构

小集合

  • List<String> names = List.of("Peter", "Paul", "Mary");
    Set<Integer> numbers = Set.of(2, 3, 5);Map<String, Integer> scores = Map.of("Peter", 2, "Paul", 3, "Mary", 5);
    
  • 以上集合不可更改,需要更改的话

var names = new ArrayList<>(List.of("Peter", "Paul", "Mary"));

子范围

  • 可以为很多集合建立子范围视图
List<Employee> group2 = staff.subList(10, 20); //10~19group2.clear(); // 元素会自动的从staff中删除SortedSet<E> subSet(E from, E to);// 返回大于from, 小于to的所有元素构成的子集

不可修改视图

  • 这些视图对现有的集合增加了一个运行检查.如果发现试图对集合修改,抛出异常
  • P406

同步视图

  • Collections类的静态方法synchronizedMap方法可以将任何一个映射转换成有同步访问方法的Map
var map = Collections.synchronizedMap(new HashMaP<String, Employee>());

算法

为什么使用泛型算法

  • 数组中最大元素:
if(a.length == 0) throw new NoSuchElementException();
T largest = a[0];for (int i = 0; i < a.length; i++) {if (largest.compareTo(a[i]) < 0) {largest = a[i];}
}
  • 数组列表中最大元素
if(a.size() == 0) throw new NoSuchElementException();
T largest = a.get(0);for (int i = 0; i < a.size(); i++) {if (largest.compareTo(a.get(i)) < 0) {largest = a.get(i);}
}
  • 链表没有高效随机访问操作,可以使用迭代器
if (l.isEmpty())  throw new NoSuchElementException();
Iterator<T> it = l.iterator();
T largest = it.next();
while (it.hasNext()) {T next = it.next();if (largest.compareTo(next) < 0) {largest = next;}
}
  • 可以使用max方法实现能够接受任何实现了Collection接口的对象
public static <T extends Comparable> T max(Collection<T> collection) {if (collection.isEmpty()) throw new NoSuchElementException();Iterator<T> iter = collection.iterator();T largest = iter.next();while (iter.hasNext()) {T next = iter.next();if (largest.compareTo(next) < 0) {largest = next;}}return largest;
}

排序与混排

  • sort方法对实现了List接口的集合排序

Colletion.sort(staff);

  • 列表元素实现了Comparable接口
staff.sort(Comparator.comparingDouble(Employee::getSalary))
  • 逆序Collection.reverseOrder()

  • staff.sort(Comparator.comparingDouble(Employee::getSalary).reversed())

  • 列表是可修改的支持set方法,可改变大小的支持add, remove方法

package chapter9_set.shuffle;import java.util.*;public class ShuffleTest {public static void main(String[] args) {var numbers = new ArrayList<Integer>();for (int i = 1; i < 49; i++) {numbers.add(i);}Collections.shuffle(numbers);List<Integer> winningCombination = numbers.subList(0, 10);Collections.sort(winningCombination);System.out.println(winningCombination);}
}

二分查找

  • CollectionbinarySearch方法实现了二分查找算法,要求集合必须有序
  • 集合必须实现List接口, 如果没有采用Comparable接口的CompareTo方法进行排序,那么需要提供一个比较器对象
i = Collection.binarySearch(c, element, comparator);

返回非负值:匹配对象的索引; 返回负值, 插入位置为-i-1

  • 如果提供的是链表则退化为线性查找

简单算法

  • P416

批操作

  • l1.retainAll(l2);
    l1.removeAll(l2);
    
  • 键集是映射的一个视图,staff.keySet().removeAll(terminatedIDs);键和相关的员工名字会自动的从映射中删除


集合和数组的转换

  • 数组转换为集合:
String[] names = ;
var name = new HashSet<>(List.of(names));
  • 集合得到数组使用toArray方法,返回对象数组
String[] values = staff.toArray(new String[0));

遗留的集合

  • Stack类,有pop, push方法, 扩展了Vector
  • peek返回栈顶元素

位集

  • BitSet: 高效存储位序列

//计算前两百万位素数数量 计数使用时间
package chapter9_set.sieve;import java.util.*;public class Sieve {public static void main(String[] args) {int n = 2000000;long start = System.currentTimeMillis();int i;int count = 0;var bitSet = new BitSet(n + 1);for (i = 2; i <= n; i++)bitSet.set(i);i = 2;while (i * i <= n) {if (bitSet.get(i)) {count++;int k = 2 * i;while (k <= n) {bitSet.clear(k);k += i;}}i++;}// i = sqrt(n);while (i <= n) {if (bitSet.get(i))count++;i++;}long end = System.currentTimeMillis();System.out.println("From 2~2000000, there are " + count  + " primes.");System.out.println("Time consumed:" + (end - start));}
}

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

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

相关文章

30多岁程序员老W,无奈选择转行!问题出在哪?

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一有一天&#xff0c;一位同事跟我说&#xff1a;老w已经改行做美缝去了&#xff0c;你怎么看&#xff1f;我想了想&#xff0c;说&#xff1a;他大概终于做出了眼下最符合他…

一维前缀和

代码如下&#xff1a; #include <iostream> using namespace std; const int N 1010; int a[N], s[N];int main() {int n;cin >> n;for (int i 1; i < n; i) {cin >> a[i];//原数组s[i] s[i - 1] a[i];}for (int i 1; i < n; i)cout << s[…

HttpClientFactory的套路,你知多少?

背景ASP.NET Core 在 2.1 之后推出了具有弹性 HTTP 请求能力的 HttpClient 工厂类 HttpClientFactory。替换的初衷还是简单摆一下&#xff1a;① using(var client new HttpClient()) 调用的 Dispose() 方法并不会立即释放底层 Socket 连接&#xff0c;新建 Socket 需要时间&a…

CoreJava 笔记总结-第十二章 并发-1

第十二章 并发 线程 package chapter12_concurrent.threads;public class ThreadsTest {public static final int DELAY 10;public static final int STEPS 100;public static final double MAX_AMOUNT 1000;public static void main(String[] args) {var bank new Bank(…

走迷宫-双向bfs解法

双向bfs适用于知道起点和终点的状态下使用&#xff0c;从起点和终点两个方向开始进行搜索&#xff0c;可以非常大的提高单个bfs的搜索效率同样&#xff0c;实现也是通过队列的方式&#xff0c;可以设置两个队列&#xff0c;一个队列保存从起点开始搜索的状态&#xff0c;另一个…

.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记...

16 | 选项数据热更新&#xff1a;让服务感知配置的变化选项框架还有两个关键类型&#xff1a;1、IOptionsMonitor2、IOptionsSnapshot场景&#xff1a;1、范围作用域类型使用 IOptinsSnapshot2、单例服务使用 IOptionsMonitor通过代码更新选项&#xff1a;IPostConfigureOption…

CoreJava 笔记总结-第十二章 并发-2

文章目录第十二章 并发synchronized关键字同步块监视器概念volatile字段final变量原子性死锁线程安全的集合阻塞队列映射条目的原子更新对并发散列映射的批操作并行数组算法同步包装器任务和线程池Callable, FutureExecutor执行器fork-in框架异步计算可完成Future组合可完成Fut…

八数码问题II-bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

华为任职资格_看了华为的任职资格体系,你就明白员工为啥这么拼?

提到华为的18万奋斗者&#xff0c;职场上没人不竖起大拇指。而优秀人才的背后&#xff0c;就像任正非曾说过的那样&#xff0c;华为的成功&#xff0c;很大意义上讲就是人力资源的成功。华为的人力资源管理最有代表性的&#xff0c;除了狼性文化和薪酬绩效外&#xff0c;就是任…

如何使用有序GUID提升数据库读写性能

源宝导读&#xff1a;数据库设计时&#xff0c;经常会使用GUID作为表的主键&#xff0c;但由于GUID的随机性会导致数据库在读写数据时效率严重下降&#xff0c;影响应用程序整体性能。本文将深入探讨如何通过使用有序GUID提升数据读写的性能。一、背景常见的数据库设计是使用连…

八数码问题II-双向bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

MarkDown语法, 快捷键,Dos命令

文章目录MarkDown 语法计算机软件快捷键Dos命令MarkDown 语法 字体: 斜体, 粗体, 删除图片: ![title](link)超链接: [words](link)引用>标题列表表格 名字|性别|生日 31辅导班VS看复旦南开都是vs1ds代码块 分割线*** 计算机软件 系统软件应用软件DOS, Windows, Unix,…

《商业洞察力30讲》学习笔记(上)

【洞察力】| 作者 / Edison Zhou这是恰童鞋骚年的第197篇原创文章学习洞察力&#xff0c;也是新时代IT人员的一门进阶必修课...1学习背景2019年下半年至今&#xff0c;在领导的推荐下学习了刘润老师的《商业洞察力30讲》&#xff0c;刷新了我对于事物的认知&#xff0c;也为我提…

[蓝桥杯][历届试题]九宫重排-双向bfs和map标记

题目描述 如下面第一个图的九宫格中&#xff0c;放着 1~8 的数字卡片&#xff0c;还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动&#xff0c;可以形成第二个图所示的局面。 我们把第一个图的局面记为&#xff1a;12345678. 把第二个图的局面记…

3月数据库排行:前10整体下行,出新技术了?

DB-Engines 数据库流行度排行榜 3 月更新已发布&#xff0c;排名前二十如下&#xff1a;排名方面没有任何变动&#xff08;仅针对前十&#xff09;&#xff0c;相信很长一段时间内也都不会变动&#xff0c;毕竟巨头的位置不是一时半刻就能动摇的。不过这个月的排行榜还是有值得…

CSS3动画大全(附源码)flex布局,grid布局3d旋转,图像模糊,文字发光

CSS3动画大全(附源码)3d旋转,图像模糊,文字发光! 文章目录CSS3动画大全(附源码)3d旋转,图像模糊,文字发光!html代码cssgrid布局flex布局文字发光 & 图像放缩3d旋转 图像移动源码html代码 <body><div class"container"><div class"main"…

每日一题——LeetCode160.相交链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1&#xff1a;示例2&#xff1a;提示&#xff1a; 2. 思路3. 代码 1. 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的…

[蓝桥杯][2013年第四届真题]买不到的数目-模拟,数论

题目描述 小明开了一家糖果店。他别出心裁&#xff1a;把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。 小朋友来买糖的时候&#xff0c;他就用这两种包装来组合。当然有些糖果数目是无法组合出来的&#xff0c;比如要买 10 颗糖。 你可以用计算机测试一下&#xff0c;在…

.NET Core的HttpClient连接池管理

译者荐语&#xff1a;使用.NET Core的HttpClient连接池管理有哪些注意事项&#xff1f;本文给出了非常中肯的建议。原文来自互联网&#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。本文来源[1]史蒂…

[蓝桥杯][2014年第五届真题]兰顿蚂蚁-模拟

题目描述 兰顿蚂蚁&#xff0c;是于1986年&#xff0c;由克里斯兰顿提出来的&#xff0c;属于细胞自动机的一种。 平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。 蚂蚁的头部朝向为&#xff1a;上下左右其中一方。 蚂蚁的移动规则十分简单&#…