序
本文次要钻研一下 claudb 的 list command
LeftPushCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/LeftPushCommand.java
@Command("lpush")
@ParamLength(2)
@ParamType(DataType.LIST)
public class LeftPushCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {ImmutableList<SafeString> values = request.getParams().asList().tail().reverse();
DatabaseValue result = db.merge(safeKey(request.getParam(0)), list(values),
(oldValue, newValue) -> list(newValue.getList().appendAll(oldValue.getList())));
return RedisToken.integer(result.size());
}
}
- LeftPushCommand 实现了 DBCommand 接口,其 execute 办法提取 values,而后执行 db.merge,在 newValue.getList() 之后追加上 oldValue.getList()
LeftPopCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/LeftPopCommand.java
@Command("lpop")
@ParamLength(1)
@ParamType(DataType.LIST)
public class LeftPopCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {List<SafeString> removed = new LinkedList<>();
db.merge(safeKey(request.getParam(0)), DatabaseValue.EMPTY_LIST,
(oldValue, newValue) -> {ImmutableList<SafeString> list = oldValue.getList();
list.head().stream().forEach(removed::add);
return list(list.tail());
});
if (removed.isEmpty()) {return nullString();
} else {return string(removed.remove(0));
}
}
}
- LeftPopCommand 实现了 DBCommand 接口,其 execute 办法执行 db.merge,它先获取 oldValue.getList(),而后取出 head 增加到 removed 中,而后再通过 list.tail() 抛弃 head 作为新的后果
RightPushCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/RightPushCommand.java
@Command("rpush")
@ParamLength(2)
@ParamType(DataType.LIST)
public class RightPushCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {ImmutableList<SafeString> values = request.getParams().asList().tail();
DatabaseValue result = db.merge(safeKey(request.getParam(0)), list(values),
(oldValue, newValue) -> list(oldValue.getList().appendAll(newValue.getList())));
return integer(result.size());
}
}
- RightPushCommand 实现了 DBCommand 接口,其 execute 办法提取 values,而后执行 db.merge,在 oldValue.getList() 之后追加上 newValue.getList()
RightPopCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/RightPopCommand.java
@Command("rpop")
@ParamLength(1)
@ParamType(DataType.LIST)
public class RightPopCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {List<SafeString> removed = new LinkedList<>();
db.merge(safeKey(request.getParam(0)), DatabaseValue.EMPTY_LIST,
(oldValue, newValue) -> {ImmutableList<SafeString> list = oldValue.getList();
list.reverse().head().stream().forEach(removed::add);
return list(list.reverse().tail().reverse());
});
if (removed.isEmpty()) {return nullString();
} else {return string(removed.remove(0));
}
}
}
- RightPopCommand 实现了 DBCommand 接口,其 execute 办法执行 db.merge,它先获取 oldValue.getList(),而后取出 list 倒数的 head 增加到 removed 中,而后再通过 list.reverse().tail() 抛弃 head 再 reverse 作为新的后果
ListLengthCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/ListLengthCommand.java
@ReadOnly
@Command("llen")
@ParamLength(1)
@ParamType(DataType.LIST)
public class ListLengthCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {ImmutableList<SafeString> list = db.getList(request.getParam(0));
return integer(list.size());
}
}
- ListLengthCommand 实现了 DBCommand 接口,其 execute 办法先通过 db.getList(request.getParam(0)) 获取 list,而后返回 integer(list.size())
ListRangeCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/ListRangeCommand.java
@ReadOnly
@Command("lrange")
@ParamLength(3)
@ParamType(DataType.LIST)
public class ListRangeCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {DatabaseValue value = db.getOrDefault(safeKey(request.getParam(0)), DatabaseValue.EMPTY_LIST);
ImmutableList<SafeString> list = value.getList();
int from = Integer.parseInt(request.getParam(1).toString());
if (from < 0) {from = list.size() + from;
}
int to = Integer.parseInt(request.getParam(2).toString());
if (to < 0) {to = list.size() + to;
}
int min = Math.min(from, to);
int max = Math.max(from, to);
// TODO: use Array
ImmutableList<SafeString> result = ImmutableList.from(list.stream().skip(min).limit((max - min) + 1));
return convert(result);
} catch (NumberFormatException e) {return error("ERR value is not an integer or out of range");
}
}
}
- ListRangeCommand 实现了 DBCommand 接口,其 execute 办法先获取 list,之后修改 min 及 max,而后取 ImmutableList.from(list.stream().skip(min).limit((max – min) + 1))
ListIndexCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/ListIndexCommand.java
@ReadOnly
@Command("lindex")
@ParamLength(2)
@ParamType(DataType.LIST)
public class ListIndexCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {ImmutableList<SafeString> list = db.getList(request.getParam(0));
int index = Integer.parseInt(request.getParam(1).toString());
if (index < 0) {index = list.size() + index;
}
// TODO: fix asArray
return string(list.asArray().get(index));
} catch (NumberFormatException e) {return error("ERR value is not an integer or out of range");
} catch (IndexOutOfBoundsException e) {return nullString();
}
}
}
- ListIndexCommand 实现了 DBCommand 接口,其 execute 办法先获取 list,而后返回 string(list.asArray().get(index))
ListSetCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/list/ListSetCommand.java
@Command("lset")
@ParamLength(3)
@ParamType(DataType.LIST)
public class ListSetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {int index = Integer.parseInt(request.getParam(1).toString());
db.merge(safeKey(request.getParam(0)), DatabaseValue.EMPTY_LIST,
(oldValue, newValue) -> {ImmutableList<SafeString> oldList = oldValue.getList();
// TODO: use Array
List<SafeString> array = new ArrayList<>(oldList.toList());
array.set(index > -1 ? index : array.size() + index, request.getParam(2));
return list(array);
});
return status("OK");
} catch (NumberFormatException e) {return error("ERR value is not an integer or out of range");
} catch (IndexOutOfBoundsException e) {return error("ERR index out of range");
}
}
}
- ListSetCommand 实现了 DBCommand 接口,其 execute 办法先读取 index 参数,而后执行 db.merge,它读取 oldList,而后执行 array.set(index > -1 ? index : array.size() + index, request.getParam(2)),最初返回 list(array)
小结
claudb list 相干的 command 有 LeftPushCommand、LeftPopCommand、RightPushCommand、RightPopCommand、ListLengthCommand、ListRangeCommand、ListIndexCommand、ListSetCommand
doc
- command/list