Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions src/main/java/org/redis/implementation/RedisMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
package org.redis.implementation;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

/**
* Реализация интерфейса Map на основе Redis
*
* @author Sidorin Aleksei
* @version 1.0
* @since 17.10.2025
*/
public class RedisMap implements Map<String, String> {

private final JedisPool pool;
private final String redisKey;

public RedisMap(JedisPool pool, String redisKey) {
Objects.requireNonNull(pool, "JedisPool не должен быть null");
Objects.requireNonNull(redisKey, "redisKey не должен быть null");
this.pool = pool;
this.redisKey = redisKey;
}

/**
* Возвращает количество элементов в map
*
* @return количество элементов
*/
@Override
public int size() {
return clientJedis(jedis -> (int) jedis.hlen(redisKey));
}

/**
* Проверяет, пуст ли map
*
* @return true если map не содержит элементов, иначе false
*/
@Override
public boolean isEmpty() {
return size() == 0;
}

/**
* Проверяет, содержится ли указанный ключ в map
*
* @param key ключ для проверки
* @return true если ключ содержится в map, иначе false
* @throws IllegalArgumentException если ключ равен null
*/
@Override
public boolean containsKey(Object key) {
checkKeyNull(key);
return clientJedis(jedis -> jedis.hexists(redisKey, key.toString()));
}

/**
* Проверяет, содержится ли указанное значение в map
*
* @param value значение для проверки
* @return true если значение содержится в map, иначе false
* @throws IllegalArgumentException если значение равно null
*/
@Override
public boolean containsValue(Object value) {
if (Objects.isNull(value)) {
throw new IllegalArgumentException("Value must not be null");
}
return clientJedis(jedis -> jedis.hvals(redisKey).contains(value.toString()));

}

/**
* Возвращает значение по указанному ключу
*
* @param key ключ для поиска значения
* @return значение, соответствующее ключу, или null если ключ не найден
* @throws IllegalArgumentException если ключ равен null
*/
@Override
public String get(Object key) {
checkKeyNull(key);
return clientJedis(jedis -> jedis.hget(redisKey, key.toString()));

}

/**
* Добавляет пару ключ-значение в map
*
* @param key ключ для добавления
* @param value значение для добавления
* @return предыдущее значение, связанное с ключом, или null если ключа не было
* @throws IllegalArgumentException если ключ или значение равны null
*/
@Override
public String put(String key, String value) {
checkNull(key, value);
clientJedis(jedis -> jedis.hset(redisKey, key, value));
return clientJedis(jedis -> jedis.hget(redisKey, key));
}

/**
* Удаляет ключ и связанное с ним значение из map
*
* @param key ключ для удаления
* @return значение, которое было связано с ключом, или null если ключ не найден
* @throws IllegalArgumentException если ключ равен null
*/
@Override
public String remove(Object key) {
checkKeyNull(key);
clientJedis(jedis -> jedis.hdel(redisKey, key.toString()));
return clientJedis(jedis -> jedis.hget(redisKey, key.toString()));
}

/**
* Копирует все пары ключ-значение из указанного map в текущий map
*
* @param m map, содержащая пары ключ-значение для копирования
* @throws IllegalArgumentException если map равна null или пуста
* @throws IllegalArgumentException если любой ключ или значение в map равны null
*/
@Override
public void putAll(Map<? extends String, ? extends String> m) {
if (Objects.isNull(m) || m.isEmpty()) {
throw new IllegalArgumentException("Map must not be null");
}
clientJedis(jedis -> {
Map<String, String> redisMap = new HashMap<>();
for (Entry<? extends String, ? extends String> entry : m.entrySet()) {
checkNull(entry.getKey(), entry.getValue());
redisMap.put(entry.getKey(), entry.getValue());
}
return jedis.hmset(redisKey, redisMap);
});
}

/**
* Удаляет все элементы из map
*/
@Override
public void clear() {
clientJedis(jedis -> jedis.del(redisKey));
}

/**
* Возвращает множество всех ключей в map
*
* @return множество ключей
*/
@Override
public Set<String> keySet() {
return clientJedis(jedis -> new HashSet<>(jedis.hkeys(redisKey)));
}

/**
* Возвращает коллекцию всех значений в map
*
* @return коллекция значений
*/
@Override
public Collection<String> values() {
return clientJedis(jedis -> new ArrayList<>(jedis.hvals(redisKey)));
}

/**
* Возвращает множество всех пар ключ-значение в map
*
* @return множество пар ключ-значение
*/
@Override
public Set<Entry<String, String>> entrySet() {
return clientJedis(jedis -> {
Map<String, String> all = jedis.hgetAll(redisKey);
Set<Entry<String, String>> entries = new HashSet<>();
for (Map.Entry<String, String> entry : all.entrySet()) {
entries.add(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue()));
}
return entries;
});
}

/**
* Вспомогательный метод для выполнения операций с Jedis клиентом
*
* @param operation операция для выполнения
* @param <T> тип возвращаемого значения
* @return результат выполнения операции
*/
private <T> T clientJedis(Function<Jedis, T> operation) {
try (Jedis jedis = pool.getResource()) {
return operation.apply(jedis);
}
}

private static void checkNull(String key, String value) {
checkValueNull(value);
checkKeyNull(key);
}

private static void checkValueNull(String value) {
if (Objects.isNull(value)) {
throw new IllegalArgumentException("Value must not be null");
}
}

private static void checkKeyNull(Object key) {
if (Objects.isNull(key)) {
throw new IllegalArgumentException("Key must not be null");
}
}
}
Loading