拥抱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一起看)。每看完一个知识领域,就看参考书里面的相应章节(汪博士那本)…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
