Skip to content
Open

Dev #49

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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ build/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store
/.idea
28 changes: 28 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<assertj-core.version>3.27.6</assertj-core.version>
<mockito-core.version>5.20.0</mockito-core.version>
<testcontainers.version>1.21.3</testcontainers.version>
</properties>

<dependencies>
Expand All @@ -26,6 +29,31 @@
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>

</dependencies>

</project>
17 changes: 16 additions & 1 deletion src/main/java/org/redis/Main.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
package org.redis;

import java.util.Map;

public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
Map<String, String> redisMap = new RedisMap();
redisMap.put("key1", "value1");
redisMap.put("key2", "value2");
System.out.println(redisMap.get("key1"));
System.out.println(redisMap.get("key2"));

try (RedisMap redisMap2 = new RedisMap()) {
redisMap2.put("key1", "value12");
redisMap2.put("key2", "value23");
System.out.println(redisMap2.get("key1"));
System.out.println(redisMap2.get("key2"));
}


}
}
157 changes: 157 additions & 0 deletions src/main/java/org/redis/RedisMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package org.redis;

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

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
* Имплементация интерфейса Map работающая через Redis.
* AutoCloseable для очистки Redis после удаления объекта в java, чтобы не оставлять мусор.
*/
public class RedisMap implements Map<String, String>, AutoCloseable {

private static final String DEFAULT_URL = "localhost";
private static final int DEFAULT_PORT = 6379;
private final JedisPool jedisPool;
private final String mapId;

/**
* Конструктор, присваивает уникальный UUID в mapId при создании. Для идентификации этого объекта Map в Redis
*/
public RedisMap() {
jedisPool = new JedisPool(DEFAULT_URL, DEFAULT_PORT);
mapId = UUID.randomUUID().toString();
}

/**
* Конструктор, присваивает уникальный UUID в mapId при создании. Для идентификации этого объекта Map в Redis
*/
public RedisMap(String redisUrl, int redisPort) {
jedisPool = new JedisPool(redisUrl, redisPort);
mapId = UUID.randomUUID().toString();
}

/**
* Метод для получения соединения с Jedis. Необходимо закрвать после окончания работы.
*
* @return Соединение Jedis
*/
private Jedis getJedis() {
return jedisPool.getResource();
}

/**
* Метод для приведения key к String. Выбрасывает исключение если не удалось
*
* @param key объект для приведения
* @return строка
*/
private String getStringKey(Object key) {
if (key instanceof String stringKey) {
return stringKey;
} else {
throw new IllegalArgumentException("Key must be a String object");
}
}

@Override
public int size() {
try (Jedis jedis = getJedis()) {
return (int) jedis.hlen(mapId);
}
}

@Override
public boolean isEmpty() {
try (Jedis jedis = getJedis()) {
return jedis.hlen(mapId) == 0;
}
}

@Override
public boolean containsKey(Object key) {
try (Jedis jedis = getJedis()) {
return jedis.hexists(mapId, getStringKey(key));
}
}

@Override
public boolean containsValue(Object value) {
return values().contains(getStringKey(value));
}

@Override
public String get(Object key) {
try (Jedis jedis = getJedis()) {
return jedis.hget(mapId, getStringKey(key));
}
}

@Override
public String put(String key, String value) {
try (Jedis jedis = getJedis()) {
String prev = jedis.hget(mapId, key);
jedis.hset(mapId, key, value);
return prev;
}
}

@Override
public String remove(Object key) {
try (Jedis jedis = getJedis()) {
var keyString = getStringKey(key);
var prev = jedis.hget(mapId, keyString);
jedis.hdel(mapId, keyString);
return prev;
}
}

//String это final класс поэтому должно быть безопасно.
@SuppressWarnings("unchecked")
@Override
public void putAll(Map<? extends String, ? extends String> m) {
try (Jedis jedis = getJedis()) {
jedis.hset(mapId, (Map<String, String>) m);
}
}

@Override
public void clear() {
try (Jedis jedis = getJedis()) {
jedis.del(mapId);
}
}

@Override
public Set<String> keySet() {
try (Jedis jedis = getJedis()) {
return jedis.hkeys(mapId);
}
}

@Override
public Collection<String> values() {
try (Jedis jedis = getJedis()) {
return jedis.hvals(mapId);
}
}

@Override
public Set<Entry<String, String>> entrySet() {
try (Jedis jedis = getJedis()) {
return jedis.hgetAll(mapId).entrySet();
}
}

/**
* Закрывает ресурс, очищает все данные из Redis чтобы не оставлять мусора.
*/
@Override
public void close() {
clear();
}
}
Loading