当前位置: 首页 > news >正文

拥抱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不可变版本
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

三、新集合类型

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的各种实现
实现键行为类似值行为类似
ArrayListMultimapHashMapArrayList
HashMultimapHashMapHashSet
LinkedListMultimapLinkedHashMapLinkedList
LinkedHashMultimapLinkedHashMapLinkedHashMap
TreeMultimapTreeMapTreeSet
ImmutableListMultimapImmutableMapImmutableList
ImmutableSetMultimapImmutableMapImmutableSet

除了两个不可变形式的实现,其他所有实现都支持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实现
HashMapHashMapHashBiMap
ImmutableMapImmutableMapImmutableBiMap
EnumMapEnumMapEnumBiMap
EnumMapHashMapEnumHashBiMap
(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开发中&#xff0c;Google Guava库是处理集合的强大工具。起源于Google内部需求&#xff0c;Guava以简洁性、性能优化为理念&#xff0c;提供高效不可变集合和实用工具类。本文深入剖析Guava的核心功能&#xff0c;为开发者呈现集合操作的全新视角&am…...

运算放大器相关知识总结(1)

1、 前言 最近做了一个小项目&#xff0c;这个项目是研发一款阻抗测量仪。这个阻抗测量仪可以测量人体在不同频率下的生物电阻抗&#xff0c;该设备的核心是模拟电路&#xff0c;技术难点是减小模拟电路噪声。该项目前前忙了2个多月&#xff0c;借着研发这个项目的机会把自己掌…...

ZMQ_REQ\REP模式

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

机器人跟踪性能量化指标

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

【GitHub项目推荐--开源的坦克大战】【转载】

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

06、Kafka ------ 各个功能的作用解释(ISR 同步副本、非同步副本、自动创建主题、修改主题、删除主题)

目录 CMAK 各个功能的作用解释★ ISR副本 (同步副本&#xff09;★ 非同步副本★ 自动创建主题★ 修改主题★ 删除主题 CMAK 各个功能的作用解释 ★ ISR副本 (同步副本&#xff09; 简单来说 &#xff0c;ISR 副本 就是 Kafka 认为与 领导者副本 同步的副本。 ISR&#xff0…...

Spring Security实现详解

一、WebSecurityConfigurerAdapter 总配置类&#xff1a; 1、介绍&#xff1a;配置类 2、主要方法&#xff1a; &#xff08;1&#xff09;configure&#xff08;HttpSecurity http&#xff09; protected void configure(HttpSecurity http) throws Exception {this.logge…...

⭐Unity LeapMotion与手的相关开发

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

React16源码: React中的update和updateQueue的源码实现

React中的update和updateQueue 1 &#xff09;概述 在 ReactDOM.render 过程中&#xff0c;还需要创建一个 update 对象update 用于记录组件状态的改变的一个对象&#xff0c;它存放于Fiber对象的 updateQueue 中updateQueue&#xff0c;它是一个单向链表的结构&#xff0c;一…...

mybatisplus(service CRUD 接口)

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

GC6109——双通道5V低电压步进电机驱动芯片,低噪声、低振动,应用摄像机,机器人等产品中

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

MySQL-多表联合查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&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靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/dc/DC-1.zip 靶机地址&#xff1a;192.168.67.28 攻击机地址&#xff1a;192.168.67.3 一、信息收集 1.使用 arp-scan 命令扫描网段内存活的…...

【springboot 中集成 knife4j 时,报错 No mapping for GET /doc.html】

出现这种情况可能是项目中含有继承WebMvcConfigurationSupport的类&#xff0c;这会导致 swagger 配置失效。 解决方法&#xff0c;继承WebMvcConfigurationSupport下重写addResourceHandlers方法 Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry)…...

C++ 具名要求-全库范围的概念 -谓词(Predicate)-二元谓词(BinaryPredicate)

此页面中列出的具名要求&#xff0c;是 C 标准的规范性文本中使用的具名要求&#xff0c;用于定义标准库的期待。 某些具名要求在 C20 中正在以概念语言特性进行形式化。在那之前&#xff0c;确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做&#xf…...

MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询

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

arcgis javascript api4.x加载天地图web墨卡托(wkid:3857)坐标系

效果&#xff1a; 示例代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv&quo…...

中职组安全-win20230217-环境-解析

*任务说明&#xff1a; 仅能获取win20230217的IP地址 用户名&#xff1a;test&#xff0c;密码&#xff1a;123456 访问服务器主机,找到主机中管理员名称,将管理员名称作为Flag值提交&#xff1b; john 访问服务器主机,找到主机中补丁信息,将补丁编号作为Flag值提交&#xff…...

PMP学习考试经验总结

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

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...