拥抱Guava之集合操作
深入Guava集合操作
在Java开发中,Google Guava库是处理集合的强大工具。起源于Google内部需求,Guava以简洁性、性能优化为理念,提供高效不可变集合和实用工具类。本文深入剖析Guava的核心功能,为开发者呈现集合操作的全新视角,无论经验水平,都能获得实用技巧和深刻见解。
一、不可变集合
1、为什么使用不可变集合
不可变对象有很多优点,包括:
- 当对象被不可信的库调用时,不可变形式是安全的;
- 不可变对象被多个线程调用时,不存在竞态条件问题
- 可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
- 不可变对象因为有固定不变,可以作为常量来安全使用。
2、创建不可变集合的方式:
- copyOf方法,如ImmutableSet.copyOf(set);
- of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
- Builder工具,如:
private static final ImmutableSet<String> SET = ImmutableSet.<String>builder().add("a","b").addAll(Lists.newArrayList("c","d")).build();
此外,对有序不可变集合来说,排序是在构造集合的时候完成的,如: ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
会在构造时就把元素排序为a, b, c, d。
3、asList视图
所有不可变集合都有一个asList()方法提供ImmutableList视图,来帮助你用列表形式方便地读取集合元素。例如,你可以使用sortedSet.asList().get(k)从ImmutableSortedSet中读取第k个最小元素。
asList()返回的ImmutableList通常是——并不总是——开销稳定的视图实现,而不是简单地把元素拷贝进List。也就是说,asList返回的列表视图通常比一般的列表平均性能更好,比如,在底层集合支持的情况下,它总是使用高效的contains方法。
二、关联可变集合和不可变集合
可变集合接口 | 属于JDK还是Guava | 不可变版本 |
---|---|---|
Collection | JDK | ImmutableCollection |
List | JDK | ImmutableList |
Set | JDK | ImmutableSet |
SortedSet/NavigableSet | JDK | ImmutableSortedSet |
Map | JDK | ImmutableMap |
SortedMap | JDK | ImmutableSortedMap |
Multiset | Guava | ImmutableMultiset |
SortedMultiset | Guava | ImmutableSortedMultiset |
Multimap | Guava | ImmutableMultimap |
ListMultimap | Guava | ImmutableListMultimap |
SetMultimap | Guava | ImmutableSetMultimap |
BiMap | Guava | ImmutableBiMap |
ClassToInstanceMap | Guava | ImmutableClassToInstanceMap |
Table | Guava | ImmutableTable |
三、新集合类型
1、Multiset
Multiset可以多次添加相等元素,集合[set]概念的延伸,它的元素可以重复出现…与集合[set]相同而与元组[tuple]相反的是,Multiset元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的
可以用两种方式看待Multiset:
- 没有元素顺序限制的ArrayList
- Map<E, Integer>,键为元素,值为计数
(1)、常见方法
方法 | 描述 |
---|---|
int count(E) | 给定元素在Multiset中的计数 |
Set<E> elementSet() | Multiset中不重复元素的集合,类型为Set<E> |
Set<Multiset.Entry<E>> entrySet() | 和Map的entrySet类似,返回Set<Multiset.Entry<E>>,其中包含的Entry支持getElement()和getCount()方法 |
int add(E, int) | 增加给定元素在Multiset中的计数 |
boolean add(E element) | 增加一个指定的元素到multiset |
boolean contains(E element) | 判断此多集中是否包含指定的元素 |
boolean containsAll(Collection<?> elements) | 判断此多集至少包含一个出现指定集合的所有元素 |
remove(E, int) | 减少给定元素在Multiset中的计数,删除指定元素 |
removeAll(Collection<?> c) | 删除包含在指定集合中的元素 |
boolean retainAll(Collection<?> e) | 保持包含指定集合中的元素 |
int setCount(E, int) | 设置给定元素在Multiset中的计数,不可以为负数,添加/删除指定元素,使其达到所期望的元素个数 |
int size() | 返回集合元素的总个数(包括重复的元素) |
Iterator iterator() | 返回一个迭代器,包含Multiset的所有元素(包括重复的元素) |
(2)、示例
/*** MultiSet*/@Testpublic void multiSetTest(){Multiset<String> multiset = HashMultiset.create();List<String> list = Lists.newArrayList("a","b","c","d","a","c","d","a","d","a");multiset.addAll(list);System.out.println("a的个数:"+multiset.count("a"));System.out.println("multiset的个数:"+multiset.size());Set<String> set = multiset.elementSet();System.out.println("不重复元素:"+ Joiner.on(",").join(set));Iterator<String> iterator = multiset.iterator();System.out.println("multiset元素:"+Joiner.on(",").join(iterator));Set<Multiset.Entry<String>> entrySet = multiset.entrySet();Map<String,Integer> setMap = Maps.newHashMap();entrySet.forEach(e -> {setMap.put(e.getElement(),e.getCount());});System.out.println("元素详情:"+Joiner.on(";").withKeyValueSeparator("=").join(setMap));multiset.remove("a",2);System.out.println("删除a后,a的个数:"+multiset.count("a"));System.out.println("是否包含List:"+multiset.containsAll(Lists.newArrayList("a","c")));System.out.println("是否包含List:"+multiset.containsAll(Lists.newArrayList("a","c","e")));}
(3)、SortedMultiset
SortedMultiset是Multiset 接口的变种,它支持高效地获取指定范围的子集
2、MultiMap
Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。 可以用两种方式思考Multimap的概念:”键-单个值映射”的集合:
a -> 1 a -> 2 a ->4 b -> 3 c -> 5
或者”键-值集合映射”的映射:
a -> [1, 2, 4] b -> 3 c -> 5
一般来说,Multimap接口应该用第一种方式看待,但asMap()视图返回Map<K, Collection>,让你可以按另一种方式看待Multimap。重要的是,不会有任何键映射到空集合:一个键要么至少到一个值,要么根本就不在Multimap中。 很少会直接使用Multimap接口,更多时候你会用ListMultimap或SetMultimap接口,它们分别把键映射到List或Set。
(1)、常用方法
方法 | 描述 | 等价于 |
---|---|---|
boolean put(K, V) | 添加键到单个值的映射 | multimap.get(key).add(value) |
boolean putAll(K, Iterable<V>) | 依次添加键到多个值的映射 | Iterables.addAll(multimap.get(key), values) |
remove(K, V) | 移除键到值的映射;如果有这样的键值并成功移除,返回true。 | multimap.get(key).remove(value) |
removeAll(K) | 清除键对应的所有值,返回的集合包含所有之前映射到K的值,但修改这个集合就不会影响Multimap了。 | multimap.get(key).clear() |
replaceValues(K, Iterable<V>) | 清除键对应的所有值,并重新把key关联到Iterable中的每个元素。返回的集合包含所有之前映射到K的值。 | multimap.get(key).clear(); Iterables.addAll(multimap.get(key), values) |
Map<K,Collection<V>> asMap() | 获取MultiMap的视图,键值K,以及K对应的集合 | |
void clear() | 清除所有的键值对 | |
boolean containsEntry(Object key,Object value) | 判断是否包含key-value对应的键值对 | |
boolean containsKey(Object key) | 判断是否包含键值key | |
boolean containsValue(Object value) | 判断是否包含值value | |
Collection<Map.Entry<K,V>> entries() | MultiMap为Map<Entry>情况下,返回所有的键值对集合 | |
Collection<V> get(K k) | 返回键k对应的所有集合 | |
boolean isEmpty() | 判断MultiMap是否是空,即不包含键值对 | |
MultiSet<K> keys() | 返回所有的键值K,包含重复 | |
Set<K> keySet() | 返回所有的键值K,不重复 | |
int size() | 返回键值对的数量 | |
Collection<V> values | 返回所有的value |
(2)、示例
/*** MultiMap*/@Testpublic void multiMapTest(){Multimap<String,String> multimap = HashMultimap.create();multimap.putAll("lower",Lists.newArrayList("a","b","c","d"));multimap.putAll("upper",Lists.newArrayList("A","B","C","D"));Map<String, Collection<String>> asMap = multimap.asMap();System.out.println("asMap视图:"+Joiner.on(";").withKeyValueSeparator("=").join(asMap));Multiset<String> multisetKey = multimap.keys();System.out.println("所有的key:"+Joiner.on(",").join(multisetKey.iterator()));Set<String> keySet = multimap.keySet();System.out.println("不重复的key:"+Joiner.on(",").join(keySet));System.out.println("lower:"+Joiner.on(",").join(multimap.get("lower")));multimap.put("lower","e");System.out.println("添加后的lower:"+Joiner.on(",").join(multimap.get("lower")));System.out.println("upper:"+Joiner.on(",").join(multimap.get("upper")));multimap.remove("upper","D");System.out.println("移除元素后的upper:"+Joiner.on(",").join(multimap.get("upper")));System.out.println("是否包含lower-b:"+multimap.containsEntry("lower","b"));System.out.println("是否包含lower-b:"+multimap.containsEntry("lower","f"));System.out.println("是否包含key(upper):"+multimap.containsKey("upper"));System.out.println("是否包含value(c):"+multimap.containsValue("c"));Collection<Map.Entry<String,String>> collection = multimap.entries();System.out.println("MultiMap详情:"+Joiner.on(";").withKeyValueSeparator("=").join(collection));Collection<String> values = multimap.values();System.out.println("MultiMap所有的value:"+Joiner.on(",").join(values));}
(3)、Multimap不是Map
Multimap<K, V>不是Map<K,Collection>,虽然某些Multimap实现中可能使用了map。它们之间的显著区别包括:
-
Multimap.get(key)总是返回非null、但是可能空的集合。这并不意味着Multimap为相应的键花费内存创建了集合,而只是提供一个集合视图方便你为键增加映射值——译者注:如果有这样的键,返回的集合只是包装了Multimap中已有的集合;如果没有这样的键,返回的空集合也只是持有Multimap引用的栈对象,让你可以用来操作底层的Multimap。因此,返回的集合不会占据太多内存,数据实际上还是存放在Multimap中。
-
如果你更喜欢像Map那样,为Multimap中没有的键返回null,请使用asMap()视图获取一个Map<K, Collection<V>>。(或者用静态方法Multimaps.asMap()为ListMultimap返回一个Map<K, List<V>>。对于SetMultimap和SortedSetMultimap,也有类似的静态方法存在)
-
当且仅当有值映射到键时,Multimap.containsKey(key)才会返回true。尤其需要注意的是,如果键k之前映射过一个或多个值,但它们都被移除后,Multimap.containsKey(key)会返回false。
-
Multimap.entries()返回Multimap中所有”键-单个值映射”——包括重复键。如果你想要得到所有”键-值集合映射”,请使用asMap().entrySet()。
-
Multimap.size()返回所有”键-单个值映射”的个数,而非不同键的个数。要得到不同键的个数,请改用Multimap.keySet().size()。
(4)、Multimap的各种实现
实现 | 键行为类似 | 值行为类似 |
---|---|---|
ArrayListMultimap | HashMap | ArrayList |
HashMultimap | HashMap | HashSet |
LinkedListMultimap | LinkedHashMap | LinkedList |
LinkedHashMultimap | LinkedHashMap | LinkedHashMap |
TreeMultimap | TreeMap | TreeSet |
ImmutableListMultimap | ImmutableMap | ImmutableList |
ImmutableSetMultimap | ImmutableMap | ImmutableSet |
除了两个不可变形式的实现,其他所有实现都支持null键和null值
-
LinkedListMultimap.entries()保留了所有键和值的迭代顺序。详情见doc链接。
-
LinkedHashMultimap保留了映射项的插入顺序,包括键插入的顺序,以及键映射的所有值的插入顺序。 请注意,并非所有的Multimap都和上面列出的一样,使用Map<K, Collection<V>>来实现(特别是,一些Multimap实现用了自定义的hashTable,以最小化开销)
3、BiMap
BiMap<K, V>是特殊的Map:
- 可以用 inverse()反转BiMap<K, V>的键值映射
- 保证值是唯一的,因此 values()返回Set而不是普通的Collection
在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException异常。
(1)、常用方法
方法 | 描述 |
---|---|
V forcePut(String key, V value) | 对于特定的值,强制替换它的键 |
BiMap<K,V> inverse() | k-v键值对的转换,即v-k |
V put<K key,V value> | 关联v到k |
void putAll(Map<? extend k,? extend V> map) | 将map加入到BiMap |
Set values() | 返回BiMap映射中包含的Collection视图 |
(2)、BiMap的各种实现
键–值实现 | 值–键实现 | 对应的BiMap实现 |
---|---|---|
HashMap | HashMap | HashBiMap |
ImmutableMap | ImmutableMap | ImmutableBiMap |
EnumMap | EnumMap | EnumBiMap |
EnumMap | HashMap | EnumHashBiMap |
(3)、示例
/*** BiMap*/@Testpublic void biMapTest(){BiMap<String, String> biMap = HashBiMap.create();biMap.putAll(ImmutableMap.of("a","1","b","2","c","3","d","4","e","5"));System.out.println("所有的值:"+Joiner.on(",").join(biMap.values()));System.out.println("转换后所有的值:"+Joiner.on(",").join(biMap.inverse().values()));String v = biMap.forcePut("a","10");System.out.println("替换的值:"+v);System.out.println("所有的值:"+Joiner.on(",").join(biMap.values()));}
4、Table
Table是Guava提供的一个接口 Interface Table<R,C,V>,由rowKey+columnKey+value组成 它有两个键,一个值,和一个n行三列的数据表类似,n行取决于Table对对象中存储了多少个数据。
(1)、常用方法
方法 | 描述 |
---|---|
Set<Table.Cell<R,C,V>> cellSet() | 返回集合中的行键,列键,值三元组 |
void clear() | 清除所有的键值对 |
Map<R,V> column(C columnKey) | 获取列键对应的键值对 |
Map<C,V> row(R row) | 获取行键对应的列以及值 |
Set<C> columnKeySet() | 获取所有的列键 |
Set<R> rowKeySet() | 获取行键 |
Map<C,Map<R,V>> columnMap | 返回列键对应的行键-值的视图 |
boolean contains(Object rowKey,Object columnKey) | 判断是否包含指定的行键,列键 |
boolean containsColumn(Object columnKey) | 判断是否包含指定的列键 |
boolean containsRow(Object rowKey) | 判断是否包含指定的行键 |
boolean containsValue(Object value) | 判断是否包含值 |
V get(Object rowKey,Object columnKey) | 返回指定的行键,列键对应的值,不存在则返回null |
boolean isEmpty() | 判断集合是否为空 |
V put(Object rowKey,Object columnKey,Object value) | put值 |
void putAll(Table<? extend R,? extend C,? extend V> table) | put指定的table |
V remove(Object rowKey,Object columnKey) | 如果有,则移除指定行键,列键 |
Map<R,Map<C,V>> rowMap() | 获取每个行键对应的列键,值的视图 |
int size() | 集合的个数(行键/列键/值) |
Collection<V> values() | 集合值的集合,包括重复的 |
(2)、示例
/*** Table*/@Testpublic void tableTest(){Table<String,String,Integer> table = HashBasedTable.create();table.put("grade_1","class_1",100);table.put("grade_1","class_2",95);table.put("grade_1","class_3",80);table.put("grade_2","class_1",88);table.put("grade_2","class_2",95);table.put("grade_2","class_3",99);table.put("grade_2","class_3",100);Set<Table.Cell<String,String,Integer>> cellSet = table.cellSet();cellSet.forEach(cell -> {System.out.println("table中的行:"+cell.getRowKey()+";列:"+cell.getColumnKey()+";值:"+cell.getValue());});System.out.println("grade1对应的class:"+Joiner.on(";").withKeyValueSeparator("=").join(table.row("grade_1")));System.out.println("class1对应的grade:"+Joiner.on(";").withKeyValueSeparator("=").join(table.column("class_1")));System.out.println("所有的grade:"+Joiner.on(",").join(table.rowKeySet()));System.out.println("所有的class:"+Joiner.on(",").join(table.columnKeySet()));Map<String,Map<String,Integer>> rowMap = table.rowMap();rowMap.forEach((row,map) -> {System.out.println(row +"行对应的列值:"+Joiner.on(";").withKeyValueSeparator("=").join(map));});Map<String,Map<String,Integer>> columnMap = table.columnMap();columnMap.forEach((column,map) -> {System.out.println(column +"列对应的行值:"+Joiner.on(";").withKeyValueSeparator("=").join(map));});System.out.println("是否包含grade_1 和 class_2:"+table.contains("grade_1","class_2"));table.remove("grade_1","class_2");System.out.println("是否包含grade_1 和 class_2:"+table.contains("grade_1","class_2"));}
(3)、Table有如下几种实现:
-
HashBasedTable:本质上用HashMap<R, HashMap<C, V>>实现;
-
TreeBasedTable:本质上用TreeMap<R, TreeMap<C,V>>实现;
-
ImmutableTable:本质上用ImmutableMap<R, ImmutableMap<C, V>>实现;注:ImmutableTable对稀疏或密集的数据集都有优化。
-
ArrayTable:要求在构造时就指定行和列的大小,本质上由一个二维数组实现,以提升访问速度和密集Table的内存利用率。ArrayTable与其他Table的工作原理有点不同。
5、ClassToInstanceMap
ClassToInstanceMap是一种特殊的Map:它的键是类型,而值是符合键所指类型的对象。
为了扩展Map接口,ClassToInstanceMap额外声明了两个方法:T getInstance(Class T) 和T putInstance(Class , T),从而避免强制类型转换,同时保证了类型安全。
ClassToInstanceMap有唯一的泛型参数,通常称为B,代表Map支持的所有类型的上界。
对于ClassToInstanceMap,Guava提供了两种有用的实现:MutableClassToInstanceMap和 ImmutableClassToInstanceMap。
示例
/*** ClassToInstanceMap*/@Testpublic void classToInstanceMapTest(){ClassToInstanceMap<Number> instanceMap = MutableClassToInstanceMap.create();instanceMap.putInstance(Integer.class,123);instanceMap.putInstance(Long.class,456L);instanceMap.putInstance(Double.class,789.09);System.out.println("Integer:"+instanceMap.getInstance(Integer.class));System.out.println("Long:"+instanceMap.getInstance(Long.class));System.out.println("Double:"+instanceMap.getInstance(Double.class));}
6、RangSet
RangeSet描述了一组不相连的、非空的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并,空区间会被忽略。
结论
通过深入探索Google Guava库的集合操作,我们不仅仅发现了一个功能强大的工具,更是领略到了一个高效、简洁的Java编程理念。Guava不仅提供了基础数据结构,还为开发者提供了一整套处理集合的利器,从不可变集合到高效工具类,无一不展现出其设计的巧妙之处。
在实际项目中,Guava为我们提供了更清晰、更简单的集合操作方式,帮助我们避免了许多常见的错误和异常。它的性能优化更是让我们在处理大规模数据时事半功倍。
作为Java开发者,我们应该充分了解并灵活运用Guava库,以提高代码的可读性、可维护性和性能。无论是新手还是老手,Guava都能为我们的开发工作带来便捷和效率。
本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等
相关文章:

拥抱Guava之集合操作
深入Guava集合操作 在Java开发中,Google Guava库是处理集合的强大工具。起源于Google内部需求,Guava以简洁性、性能优化为理念,提供高效不可变集合和实用工具类。本文深入剖析Guava的核心功能,为开发者呈现集合操作的全新视角&am…...

运算放大器相关知识总结(1)
1、 前言 最近做了一个小项目,这个项目是研发一款阻抗测量仪。这个阻抗测量仪可以测量人体在不同频率下的生物电阻抗,该设备的核心是模拟电路,技术难点是减小模拟电路噪声。该项目前前忙了2个多月,借着研发这个项目的机会把自己掌…...

ZMQ_REQ\REP模式
文章内容: 学习ZMQ库中REQ\REP模式相关的内容 简介 应答模式:REQ(客户端)和REP(服务端) 典型的一问一答协议,即客户端需要首先发送hello,服务器则返回word,若客户端发…...

机器人跟踪性能量化指标
衡量机械臂关节轨迹跟踪控制的性能可以通过以下几个方面来进行: 跟踪精度:这是衡量机械臂关节轨迹跟踪控制性能的最重要的指标。它反映了机械臂实际运动轨迹与期望运动轨迹之间的偏差。跟踪精度越高,说明机械臂的控制性能越好。运动范围&…...

【GitHub项目推荐--开源的坦克大战】【转载】
坦克大战当年红遍大江南北,很多和我一样的九零后应该都有着对这个游戏的记忆。现在显示器分辨率越来越高,使用矢量图来实现像素风格游戏,可以获得非常高的展现质量。 这个项目是作者肥超花了很长时间折腾的复刻版本,所有元素都使…...

06、Kafka ------ 各个功能的作用解释(ISR 同步副本、非同步副本、自动创建主题、修改主题、删除主题)
目录 CMAK 各个功能的作用解释★ ISR副本 (同步副本)★ 非同步副本★ 自动创建主题★ 修改主题★ 删除主题 CMAK 各个功能的作用解释 ★ ISR副本 (同步副本) 简单来说 ,ISR 副本 就是 Kafka 认为与 领导者副本 同步的副本。 ISR࿰…...

Spring Security实现详解
一、WebSecurityConfigurerAdapter 总配置类: 1、介绍:配置类 2、主要方法: (1)configure(HttpSecurity http) protected void configure(HttpSecurity http) throws Exception {this.logge…...

⭐Unity LeapMotion与手的相关开发
LeapMotion 官方文档中文翻译帮助手册教程 Hand 一个Hand手对象表示了一个跟踪的手,一个手总是包含5个手指以及相关属性如:Direction,PalmPosition,和Basis(orientation). lamPosition :手掌中心到Leap设备原点以毫米测量的距离 PalmVelocity :手掌移…...

React16源码: React中的update和updateQueue的源码实现
React中的update和updateQueue 1 )概述 在 ReactDOM.render 过程中,还需要创建一个 update 对象update 用于记录组件状态的改变的一个对象,它存放于Fiber对象的 updateQueue 中updateQueue,它是一个单向链表的结构,一…...

mybatisplus(service CRUD 接口)
一、我们在控制器层都是调用Service层,不会直接调用仓储层。现在我给大家介绍一下怎么快速实现Service 的CRUD 定义接口:IProductService 继承IService<实体> package com.saas.plusdemo;import com.baomidou.mybatisplus.extension.service.ISe…...

GC6109——双通道5V低电压步进电机驱动芯片,低噪声、低振动,应用摄像机,机器人等产品中
GC6109是双通道5V低电压步进电机驱动器,具有低噪声、低振动的特点,特别适用于相机的变焦和对焦系统,万向节和其他精密、低噪声的STM控制系统。该芯片为每个通道集成了256微步驱动器。带SPl接口,用户可以方便地调整驱动器的参数。内…...

MySQL-多表联合查询
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL 🍹文章作者技术和水平很有限,如果文中出现错误&am…...

商城小程序(8.购物车页面)
目录 一、商品列表区域1、渲染购物车商品列表的标题区域2、渲染商品列表区域的基本结构3、为my-goods组件封装radio勾选状态4、为my-goods组件封装radio-change事件5、修改购物车中商品的选择状态6、为my-goods组件封装NumberBox7、为my-goods封装num-change事件8、修改购物车商…...

[Vulnhub靶机] DC-1
[Vulnhub靶机] DC-1靶机渗透思路及方法(个人分享) 靶机下载地址: https://download.vulnhub.com/dc/DC-1.zip 靶机地址:192.168.67.28 攻击机地址:192.168.67.3 一、信息收集 1.使用 arp-scan 命令扫描网段内存活的…...

【springboot 中集成 knife4j 时,报错 No mapping for GET /doc.html】
出现这种情况可能是项目中含有继承WebMvcConfigurationSupport的类,这会导致 swagger 配置失效。 解决方法,继承WebMvcConfigurationSupport下重写addResourceHandlers方法 Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry)…...

C++ 具名要求-全库范围的概念 -谓词(Predicate)-二元谓词(BinaryPredicate)
此页面中列出的具名要求,是 C 标准的规范性文本中使用的具名要求,用于定义标准库的期待。 某些具名要求在 C20 中正在以概念语言特性进行形式化。在那之前,确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做…...

MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询
MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询 MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询 com.github.dreamyoung mprelation 0.0.3.2-RELEASE 注解工具使用优缺点: 优点: 使用简单…...

arcgis javascript api4.x加载天地图web墨卡托(wkid:3857)坐标系
效果: 示例代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv&quo…...

中职组安全-win20230217-环境-解析
*任务说明: 仅能获取win20230217的IP地址 用户名:test,密码:123456 访问服务器主机,找到主机中管理员名称,将管理员名称作为Flag值提交; john 访问服务器主机,找到主机中补丁信息,将补丁编号作为Flag值提交ÿ…...

PMP学习考试经验总结
PMP备考日程计划表 我的PMP的备考大概花了三个月的时间, 可以分为以下几个阶段: Week 1-4: 读完PMBoK 前面7个知识领域(中英文版PMBoK一起看)。每看完一个知识领域,就看参考书里面的相应章节(汪博士那本)…...

leetcode206.反转链表
https://leetcode.cn/problems/reverse-linked-list/description/ 题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2: 输入&am…...

python每日学17:控制推导逻辑的子表达式不要超过两个
背景:今天放假在家,《python学习手册》不在身边,所以今天学习《Effective Python: 编写高质量Python代码的90个有效方法》第28条《控制推导逻辑的子表达式不要超过两个》,这本书已经是第二版了,第一版是《编写高质量py…...

地质时间与数值模拟时间转换(mm/Ma-->m/s)
一百万年(1Ma)等于315,576,000,0003.15576e11秒。 计算方法如下: 一年通常定义为365天(非闰年)。每天有24小时。每小时有60分钟。每分钟有60秒。 所以,一年的秒数为: 365天 24小时/天 60分钟/小时 60秒/分钟 31…...

linux文件描述符管理
在实际的项目开发中,文件描述符是经常用到的并且在释放资源过程中也是很容易忽略的,使用之后不释放就会增加cpu负担,无异于内存泄漏;所以时刻掌握文件描述符的状态是非常重要的!下面介绍文件描述符的管理方法。 1. 文…...

谷歌翻译不能使用 host添加IP
谷歌浏览器翻译不能使用解决教程_142.250.100.90 translate.googleapis.com-CSDN博客...

Redis命令 - Lists命令组常用命令
先创建一个 key 叫做 mylist,mylist存一个list。 list数据类型底层是一个链表。先进后出,后进先出。 命令中的L(Left)、R(Right)代表链表的头部L(下标0的位置)和尾部R(…...

切分大文件sql为小份
数据库太大了,整个备份导入出问题或者慢,需要将整个库按照表分割(一个表一个sql文件) 环境 win10 工具:python3.7pycharm 要分割的文件大小:6G,sql文件import redbname with open(best**.sql,…...

最新版CleanMyMac X4.14.7智能清理mac磁盘垃圾工具
CleanMyMac X是一款专业的Mac清理软件,可智能清理mac磁盘垃圾和多余语言安装包,快速释放电脑内存,轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软件,修复系统漏洞,一键扫描和优化Mac系统,…...

数据割据:当代社会数据治理的挑战
数据割据是指各个组织、企业或政府机构在数据的采集、存储和使用上形成了相对独立的局面,彼此之间缺乏有效的数据共享和流通机制。这种割据现象导致了数据的重复采集、冗余存储以及信息孤岛的出现,不仅浪费了大量的资源,还制约了数据的价值发…...

逻辑回归(解决分类问题)
定义:逻辑回归是一种用于解决分类问题的统计学习方法。它通过对数据进行建模,预测一个事件发生的概率。逻辑回归通常用于二元分类问题,即将数据分为两个类别。它基于线性回归模型,但使用了逻辑函数(也称为S形函数&…...