Files
hutool/hutool-setting/src/main/java/cn/hutool/setting/GroupedMap.java
2022-09-04 20:57:26 +08:00

319 lines
7.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cn.hutool.setting;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
/**
* 基于分组的Map<br>
* 此对象方法线程安全
*
* @author looly
* @since 4.0.11
*/
public class GroupedMap extends LinkedHashMap<String, LinkedHashMap<String, String>> {
private static final long serialVersionUID = -7777365130776081931L;
private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
private final ReadLock readLock = cacheLock.readLock();
private final WriteLock writeLock = cacheLock.writeLock();
private int size = -1;
/**
* 获取分组对应的值如果分组不存在或者值不存在则返回null
*
* @param group 分组
* @param key 键
* @return 值如果分组不存在或者值不存在则返回null
*/
public String get(final String group, final String key) {
readLock.lock();
try {
final LinkedHashMap<String, String> map = this.get(StrUtil.emptyIfNull(group));
if (MapUtil.isNotEmpty(map)) {
return map.get(key);
}
} finally {
readLock.unlock();
}
return null;
}
@Override
public LinkedHashMap<String, String> get(final Object key) {
readLock.lock();
try {
return super.get(key);
} finally {
readLock.unlock();
}
}
/**
* 总的键值对数
*
* @return 总键值对数
*/
@Override
public int size() {
writeLock.lock();
try {
if (this.size < 0) {
this.size = 0;
for (final LinkedHashMap<String, String> value : this.values()) {
this.size += value.size();
}
}
} finally {
writeLock.unlock();
}
return this.size;
}
/**
* 将键值对加入到对应分组中
*
* @param group 分组
* @param key 键
* @param value 值
* @return 此key之前存在的值如果没有返回null
*/
public String put(String group, final String key, final String value) {
group = StrUtil.emptyIfNull(group).trim();
writeLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.computeIfAbsent(group, k -> new LinkedHashMap<>());
this.size = -1;
return valueMap.put(key, value);
} finally {
writeLock.unlock();
}
}
/**
* 加入多个键值对到某个分组下
*
* @param group 分组
* @param m 键值对
* @return this
*/
public GroupedMap putAll(final String group, final Map<? extends String, ? extends String> m) {
for (final Entry<? extends String, ? extends String> entry : m.entrySet()) {
this.put(group, entry.getKey(), entry.getValue());
}
return this;
}
/**
* 从指定分组中删除指定值
*
* @param group 分组
* @param key 键
* @return 被删除的值如果值不存在返回null
*/
public String remove(String group, final String key) {
group = StrUtil.emptyIfNull(group).trim();
writeLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.remove(key);
}
} finally {
writeLock.unlock();
}
return null;
}
/**
* 某个分组对应的键值对是否为空
*
* @param group 分组
* @return 是否为空
*/
public boolean isEmpty(String group) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.isEmpty();
}
} finally {
readLock.unlock();
}
return true;
}
/**
* 是否为空,如果多个分组同时为空,也按照空处理
*
* @return 是否为空,如果多个分组同时为空,也按照空处理
*/
@Override
public boolean isEmpty() {
return this.size() == 0;
}
/**
* 指定分组中是否包含指定key
*
* @param group 分组
* @param key 键
* @return 是否包含key
*/
public boolean containsKey(String group, final String key) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.containsKey(key);
}
} finally {
readLock.unlock();
}
return false;
}
/**
* 指定分组中是否包含指定值
*
* @param group 分组
* @param value 值
* @return 是否包含值
*/
public boolean containsValue(String group, final String value) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.containsValue(value);
}
} finally {
readLock.unlock();
}
return false;
}
/**
* 清除指定分组下的所有键值对
*
* @param group 分组
* @return this
*/
public GroupedMap clear(String group) {
group = StrUtil.emptyIfNull(group).trim();
writeLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
valueMap.clear();
}
} finally {
writeLock.unlock();
}
return this;
}
@Override
public Set<String> keySet() {
readLock.lock();
try {
return super.keySet();
} finally {
readLock.unlock();
}
}
/**
* 指定分组所有键的Set
*
* @param group 分组
* @return 键Set
*/
public Set<String> keySet(String group) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.keySet();
}
} finally {
readLock.unlock();
}
return Collections.emptySet();
}
/**
* 指定分组下所有值
*
* @param group 分组
* @return 值
*/
public Collection<String> values(String group) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.values();
}
} finally {
readLock.unlock();
}
return Collections.emptyList();
}
@Override
public Set<java.util.Map.Entry<String, LinkedHashMap<String, String>>> entrySet() {
readLock.lock();
try {
return super.entrySet();
} finally {
readLock.unlock();
}
}
/**
* 指定分组下所有键值对
*
* @param group 分组
* @return 键值对
*/
public Set<Entry<String, String>> entrySet(String group) {
group = StrUtil.emptyIfNull(group).trim();
readLock.lock();
try {
final LinkedHashMap<String, String> valueMap = this.get(group);
if (MapUtil.isNotEmpty(valueMap)) {
return valueMap.entrySet();
}
} finally {
readLock.unlock();
}
return Collections.emptySet();
}
@Override
public String toString() {
readLock.lock();
try {
return super.toString();
} finally {
readLock.unlock();
}
}
}