diff --git a/src/main/java/org/redisson/RedissonLexSortedSet.java b/src/main/java/org/redisson/RedissonLexSortedSet.java index 5ed50162f..b5bdf84a9 100644 --- a/src/main/java/org/redisson/RedissonLexSortedSet.java +++ b/src/main/java/org/redisson/RedissonLexSortedSet.java @@ -196,7 +196,7 @@ public class RedissonLexSortedSet extends RedissonScoredSortedSet implem params.add(0); params.add(param); } - return commandExecutor.writeAsync(getName(), codec, RedisCommands.ZADD, getName(), params.toArray()); + return commandExecutor.writeAsync(getName(), codec, RedisCommands.ZADD_BOOL, getName(), params.toArray()); } @Override diff --git a/src/main/java/org/redisson/RedissonLexSortedSetReactive.java b/src/main/java/org/redisson/RedissonLexSortedSetReactive.java new file mode 100644 index 000000000..05368ba78 --- /dev/null +++ b/src/main/java/org/redisson/RedissonLexSortedSetReactive.java @@ -0,0 +1,141 @@ +/** + * Copyright 2014 Nikita Koksharov, Nickolay Borbit + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.reactivestreams.Publisher; +import org.redisson.client.codec.StringCodec; +import org.redisson.client.protocol.RedisCommands; +import org.redisson.core.RLexSortedSetReactive; + +public class RedissonLexSortedSetReactive extends RedissonScoredSortedSetReactive implements RLexSortedSetReactive { + + public RedissonLexSortedSetReactive(CommandReactiveExecutor commandExecutor, String name) { + super(StringCodec.INSTANCE, commandExecutor, name); + } + + @Override + public Publisher removeRangeHeadByLex(String toElement, boolean toInclusive) { + String toValue = value(toElement, toInclusive); + return commandExecutor.writeObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZREMRANGEBYLEX, getName(), "-", toValue); + } + + @Override + public Publisher removeRangeTailByLex(String fromElement, boolean fromInclusive) { + String fromValue = value(fromElement, fromInclusive); + return commandExecutor.writeObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZREMRANGEBYLEX, getName(), fromValue, "+"); + } + + @Override + public Publisher removeRangeByLex(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive) { + String fromValue = value(fromElement, fromInclusive); + String toValue = value(toElement, toInclusive); + + return commandExecutor.writeObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZREMRANGEBYLEX, getName(), fromValue, toValue); + } + + @Override + public Publisher> lexRangeHead(String toElement, boolean toInclusive) { + String toValue = value(toElement, toInclusive); + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), "-", toValue); + } + + @Override + public Publisher> lexRangeTail(String fromElement, boolean fromInclusive) { + String fromValue = value(fromElement, fromInclusive); + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), fromValue, "+"); + } + + + @Override + public Publisher> lexRange(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive) { + String fromValue = value(fromElement, fromInclusive); + String toValue = value(toElement, toInclusive); + + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), fromValue, toValue); + } + + @Override + public Publisher> lexRangeHead(String toElement, boolean toInclusive, int offset, int count) { + String toValue = value(toElement, toInclusive); + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), "-", toValue, "LIMIT", offset, count); + } + + @Override + public Publisher> lexRangeTail(String fromElement, boolean fromInclusive, int offset, int count) { + String fromValue = value(fromElement, fromInclusive); + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), fromValue, "+", "LIMIT", offset, count); + } + + @Override + public Publisher> lexRange(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive, int offset, int count) { + String fromValue = value(fromElement, fromInclusive); + String toValue = value(toElement, toInclusive); + + return commandExecutor.readObservable(getName(), StringCodec.INSTANCE, RedisCommands.ZRANGEBYLEX, getName(), fromValue, toValue, "LIMIT", offset, count); + } + + @Override + public Publisher lexCountTail(String fromElement, boolean fromInclusive) { + String fromValue = value(fromElement, fromInclusive); + + return commandExecutor.readObservable(getName(), RedisCommands.ZLEXCOUNT, getName(), fromValue, "+"); + } + + @Override + public Publisher lexCountHead(String toElement, boolean toInclusive) { + String toValue = value(toElement, toInclusive); + + return commandExecutor.readObservable(getName(), RedisCommands.ZLEXCOUNT, getName(), "-", toValue); + } + + @Override + public Publisher lexCount(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive) { + String fromValue = value(fromElement, fromInclusive); + String toValue = value(toElement, toInclusive); + + return commandExecutor.readObservable(getName(), RedisCommands.ZLEXCOUNT, getName(), fromValue, toValue); + } + + private String value(String fromElement, boolean fromInclusive) { + String fromValue = fromElement.toString(); + if (fromInclusive) { + fromValue = "[" + fromValue; + } else { + fromValue = "(" + fromValue; + } + return fromValue; + } + + @Override + public Publisher add(String e) { + return commandExecutor.writeObservable(getName(), codec, RedisCommands.ZADD, getName(), 0, e); + } + + @Override + public Publisher addAll(Collection c) { + List params = new ArrayList(2*c.size()); + for (Object param : c) { + params.add(0); + params.add(param); + } + return commandExecutor.writeObservable(getName(), codec, RedisCommands.ZADD, getName(), params.toArray()); + } + +} diff --git a/src/main/java/org/redisson/RedissonReactive.java b/src/main/java/org/redisson/RedissonReactive.java index c649e6dea..274af7014 100644 --- a/src/main/java/org/redisson/RedissonReactive.java +++ b/src/main/java/org/redisson/RedissonReactive.java @@ -30,6 +30,7 @@ import org.redisson.connection.SentinelConnectionManager; import org.redisson.connection.SingleConnectionManager; import org.redisson.core.RBucketReactive; import org.redisson.core.RHyperLogLogReactive; +import org.redisson.core.RLexSortedSetReactive; import org.redisson.core.RListReactive; import org.redisson.core.RMap; import org.redisson.core.RMapReactive; @@ -151,6 +152,11 @@ public class RedissonReactive implements RedissonReactiveClient { return new RedissonScoredSortedSetReactive(codec, commandExecutor, name); } + @Override + public RLexSortedSetReactive getLexSortedSet(String name) { + return new RedissonLexSortedSetReactive(commandExecutor, name); + } + @Override public void shutdown() { connectionManager.shutdown(); diff --git a/src/main/java/org/redisson/RedissonReactiveClient.java b/src/main/java/org/redisson/RedissonReactiveClient.java index b0f8fd657..235bcc470 100644 --- a/src/main/java/org/redisson/RedissonReactiveClient.java +++ b/src/main/java/org/redisson/RedissonReactiveClient.java @@ -20,6 +20,8 @@ import java.util.List; import org.redisson.client.codec.Codec; import org.redisson.core.RBucketReactive; import org.redisson.core.RHyperLogLogReactive; +import org.redisson.core.RLexSortedSet; +import org.redisson.core.RLexSortedSetReactive; import org.redisson.core.RListReactive; import org.redisson.core.RMap; import org.redisson.core.RMapReactive; @@ -93,16 +95,16 @@ public interface RedissonReactiveClient { RScoredSortedSetReactive getScoredSortedSet(String name, Codec codec); -// /** -// * Returns String based Redis Sorted Set instance by name -// * All elements are inserted with the same score during addition, -// * in order to force lexicographical ordering -// * -// * @param name -// * @return -// */ -// RLexSortedSet getLexSortedSet(String name); -// + /** + * Returns String based Redis Sorted Set instance by name + * All elements are inserted with the same score during addition, + * in order to force lexicographical ordering + * + * @param name + * @return + */ + RLexSortedSetReactive getLexSortedSet(String name); + // /** // * Returns topic instance by name. // * diff --git a/src/main/java/org/redisson/RedissonScoredSortedSet.java b/src/main/java/org/redisson/RedissonScoredSortedSet.java index 2cc642132..a128b5413 100644 --- a/src/main/java/org/redisson/RedissonScoredSortedSet.java +++ b/src/main/java/org/redisson/RedissonScoredSortedSet.java @@ -67,7 +67,7 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc @Override public Future addAsync(double score, V object) { - return commandExecutor.writeAsync(getName(), codec, RedisCommands.ZADD, getName(), BigDecimal.valueOf(score).toPlainString(), object); + return commandExecutor.writeAsync(getName(), codec, RedisCommands.ZADD_BOOL, getName(), BigDecimal.valueOf(score).toPlainString(), object); } @Override @@ -122,7 +122,7 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc @Override public Future sizeAsync() { - return commandExecutor.readAsync(getName(), codec, RedisCommands.ZCARD, getName()); + return commandExecutor.readAsync(getName(), codec, RedisCommands.ZCARD_INT, getName()); } @Override @@ -152,7 +152,7 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc @Override public Future rankAsync(V o) { - return commandExecutor.readAsync(getName(), codec, RedisCommands.ZRANK, getName(), o); + return commandExecutor.readAsync(getName(), codec, RedisCommands.ZRANK_INT, getName(), o); } private ListScanResult scanIterator(InetSocketAddress client, long startPos) { diff --git a/src/main/java/org/redisson/RedissonScoredSortedSetReactive.java b/src/main/java/org/redisson/RedissonScoredSortedSetReactive.java index fcbcf7b64..6cd50c388 100644 --- a/src/main/java/org/redisson/RedissonScoredSortedSetReactive.java +++ b/src/main/java/org/redisson/RedissonScoredSortedSetReactive.java @@ -56,7 +56,7 @@ public class RedissonScoredSortedSetReactive extends RedissonExpirableReactiv @Override public Publisher add(double score, V object) { - return commandExecutor.writeObservable(getName(), codec, RedisCommands.ZADD, getName(), BigDecimal.valueOf(score).toPlainString(), object); + return commandExecutor.writeObservable(getName(), codec, RedisCommands.ZADD_BOOL, getName(), BigDecimal.valueOf(score).toPlainString(), object); } public Publisher removeRangeByRank(int startIndex, int endIndex) { @@ -82,7 +82,7 @@ public class RedissonScoredSortedSetReactive extends RedissonExpirableReactiv } @Override - public Publisher size() { + public Publisher size() { return commandExecutor.readObservable(getName(), codec, RedisCommands.ZCARD, getName()); } @@ -97,7 +97,7 @@ public class RedissonScoredSortedSetReactive extends RedissonExpirableReactiv } @Override - public Publisher rank(V o) { + public Publisher rank(V o) { return commandExecutor.readObservable(getName(), codec, RedisCommands.ZRANK, getName(), o); } diff --git a/src/main/java/org/redisson/RedissonSetReactive.java b/src/main/java/org/redisson/RedissonSetReactive.java index 2cd888c7a..cec084ec2 100644 --- a/src/main/java/org/redisson/RedissonSetReactive.java +++ b/src/main/java/org/redisson/RedissonSetReactive.java @@ -69,7 +69,7 @@ public class RedissonSetReactive extends RedissonExpirableReactive implements @Override public Publisher add(V e) { - return commandExecutor.writeObservable(getName(), codec, RedisCommands.SADD_SINGLE, getName(), e); + return commandExecutor.writeObservable(getName(), codec, RedisCommands.SADD, getName(), e); } @Override diff --git a/src/main/java/org/redisson/client/protocol/RedisCommands.java b/src/main/java/org/redisson/client/protocol/RedisCommands.java index 2efc232b3..0a563db01 100644 --- a/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -64,13 +64,16 @@ public interface RedisCommands { RedisStrictCommand ASKING = new RedisStrictCommand("ASKING", new VoidReplayConvertor()); RedisStrictCommand READONLY = new RedisStrictCommand("READONLY", new VoidReplayConvertor()); - RedisCommand ZADD = new RedisCommand("ZADD", new BooleanAmountReplayConvertor(), 3); + RedisCommand ZADD_BOOL = new RedisCommand("ZADD", new BooleanAmountReplayConvertor(), 3); + RedisCommand ZADD = new RedisCommand("ZADD", 3); RedisCommand ZREM = new RedisCommand("ZREM", new BooleanAmountReplayConvertor(), 2); - RedisStrictCommand ZCARD = new RedisStrictCommand("ZCARD", new IntegerReplayConvertor()); + RedisStrictCommand ZCARD_INT = new RedisStrictCommand("ZCARD", new IntegerReplayConvertor()); + RedisStrictCommand ZCARD = new RedisStrictCommand("ZCARD"); RedisStrictCommand ZLEXCOUNT = new RedisStrictCommand("ZLEXCOUNT", new IntegerReplayConvertor()); RedisCommand ZSCORE_CONTAINS = new RedisCommand("ZSCORE", new BooleanNotNullReplayConvertor(), 2); RedisStrictCommand ZSCORE = new RedisStrictCommand("ZSCORE", new DoubleReplayConvertor()); - RedisCommand ZRANK = new RedisCommand("ZRANK", new IntegerReplayConvertor(), 2); + RedisCommand ZRANK_INT = new RedisCommand("ZRANK", new IntegerReplayConvertor(), 2); + RedisStrictCommand ZRANK = new RedisStrictCommand("ZRANK", 2); RedisCommand ZRANGE_SINGLE = new RedisCommand("ZRANGE", new ObjectFirstResultReplayDecoder()); RedisCommand> ZRANGE = new RedisCommand>("ZRANGE", new ObjectListReplayDecoder()); RedisStrictCommand ZREMRANGEBYRANK = new RedisStrictCommand("ZREMRANGEBYRANK", new IntegerReplayConvertor()); diff --git a/src/main/java/org/redisson/client/protocol/RedisStrictCommand.java b/src/main/java/org/redisson/client/protocol/RedisStrictCommand.java index b929e4e66..400eadaef 100644 --- a/src/main/java/org/redisson/client/protocol/RedisStrictCommand.java +++ b/src/main/java/org/redisson/client/protocol/RedisStrictCommand.java @@ -24,6 +24,10 @@ public class RedisStrictCommand extends RedisCommand { super(name, (Decoder)null, objectParamIndex, inParamType); } + public RedisStrictCommand(String name, int encodeParamIndex) { + super(name, null, null, null, encodeParamIndex); + } + public RedisStrictCommand(String name, MultiDecoder replayMultiDecoder) { super(name, replayMultiDecoder); } diff --git a/src/main/java/org/redisson/core/RLexSortedSetReactive.java b/src/main/java/org/redisson/core/RLexSortedSetReactive.java new file mode 100644 index 000000000..5f876156f --- /dev/null +++ b/src/main/java/org/redisson/core/RLexSortedSetReactive.java @@ -0,0 +1,52 @@ +/** + * Copyright 2014 Nikita Koksharov, Nickolay Borbit + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.core; + +import java.util.Collection; + +import org.reactivestreams.Publisher; + +public interface RLexSortedSetReactive extends RCollectionReactive { + + Publisher removeRangeByLex(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive); + + Publisher removeRangeTailByLex(String fromElement, boolean fromInclusive); + + Publisher removeRangeHeadByLex(String toElement, boolean toInclusive); + + Publisher lexCountTail(String fromElement, boolean fromInclusive); + + Publisher lexCountHead(String toElement, boolean toInclusive); + + Publisher> lexRangeTail(String fromElement, boolean fromInclusive); + + Publisher> lexRangeHead(String toElement, boolean toInclusive); + + Publisher> lexRange(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive); + + Publisher> lexRangeTail(String fromElement, boolean fromInclusive, int offset, int count); + + Publisher> lexRangeHead(String toElement, boolean toInclusive, int offset, int count); + + Publisher> lexRange(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive, int offset, int count); + + Publisher lexCount(String fromElement, boolean fromInclusive, String toElement, boolean toInclusive); + + Publisher rank(String o); + + Publisher> valueRange(int startIndex, int endIndex); + +} diff --git a/src/main/java/org/redisson/core/RScoredSortedSetAsync.java b/src/main/java/org/redisson/core/RScoredSortedSetAsync.java index 0bf2f9990..e2909d5ed 100644 --- a/src/main/java/org/redisson/core/RScoredSortedSetAsync.java +++ b/src/main/java/org/redisson/core/RScoredSortedSetAsync.java @@ -27,6 +27,8 @@ public interface RScoredSortedSetAsync extends RExpirableAsync { Future lastAsync(); + Future removeRangeByScoreAsync(double startScore, boolean startScoreInclusive, double endScore, boolean endScoreInclusive); + Future removeRangeByRankAsync(int startIndex, int endIndex); Future rankAsync(V o); diff --git a/src/main/java/org/redisson/core/RScoredSortedSetReactive.java b/src/main/java/org/redisson/core/RScoredSortedSetReactive.java index d4d0168c4..7bf0f9022 100644 --- a/src/main/java/org/redisson/core/RScoredSortedSetReactive.java +++ b/src/main/java/org/redisson/core/RScoredSortedSetReactive.java @@ -32,7 +32,7 @@ public interface RScoredSortedSetReactive extends RExpirableReactive { Publisher removeRangeByRank(int startIndex, int endIndex); - Publisher rank(V o); + Publisher rank(V o); Publisher getScore(V o); @@ -40,7 +40,7 @@ public interface RScoredSortedSetReactive extends RExpirableReactive { Publisher remove(V object); - Publisher size(); + Publisher size(); Publisher contains(Object o); diff --git a/src/test/java/org/redisson/RedissonLexSortedSetReactiveTest.java b/src/test/java/org/redisson/RedissonLexSortedSetReactiveTest.java new file mode 100644 index 000000000..3ecc8fad6 --- /dev/null +++ b/src/test/java/org/redisson/RedissonLexSortedSetReactiveTest.java @@ -0,0 +1,127 @@ +package org.redisson; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.redisson.core.RLexSortedSetReactive; + +public class RedissonLexSortedSetReactiveTest extends BaseReactiveTest { + + @Test + public void testRemoveLexRangeTail() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + Assert.assertTrue(sync(set.add("a")) == 1); + Assert.assertFalse(sync(set.add("a")) == 1); + Assert.assertTrue(sync(set.add("b")) == 1); + Assert.assertTrue(sync(set.add("c")) == 1); + Assert.assertTrue(sync(set.add("d")) == 1); + Assert.assertTrue(sync(set.add("e")) == 1); + Assert.assertTrue(sync(set.add("f")) == 1); + Assert.assertTrue(sync(set.add("g")) == 1); + + Assert.assertEquals(0, sync(set.removeRangeTailByLex("z", false)).intValue()); + + Assert.assertEquals(4, sync(set.removeRangeTailByLex("c", false)).intValue()); + MatcherAssert.assertThat(sync(set), Matchers.contains("a", "b", "c")); + Assert.assertEquals(1, sync(set.removeRangeTailByLex("c", true)).intValue()); + MatcherAssert.assertThat(sync(set), Matchers.contains("a", "b")); + } + + + @Test + public void testRemoveLexRangeHead() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + sync(set.add("a")); + sync(set.add("b")); + sync(set.add("c")); + sync(set.add("d")); + sync(set.add("e")); + sync(set.add("f")); + sync(set.add("g")); + + Assert.assertEquals(2, sync(set.removeRangeHeadByLex("c", false)).intValue()); + MatcherAssert.assertThat(sync(set), Matchers.contains("c", "d", "e", "f", "g")); + Assert.assertEquals(1, (int)sync(set.removeRangeHeadByLex("c", true))); + MatcherAssert.assertThat(sync(set), Matchers.contains("d", "e", "f", "g")); + } + + @Test + public void testRemoveLexRange() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + sync(set.add("a")); + sync(set.add("b")); + sync(set.add("c")); + sync(set.add("d")); + sync(set.add("e")); + sync(set.add("f")); + sync(set.add("g")); + + Assert.assertEquals(5, sync(set.removeRangeByLex("aaa", true, "g", false)).intValue()); + MatcherAssert.assertThat(sync(set), Matchers.contains("a", "g")); + } + + + @Test + public void testLexRangeTail() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + Assert.assertTrue(sync(set.add("a")) == 1); + Assert.assertFalse(sync(set.add("a")) == 1); + Assert.assertTrue(sync(set.add("b")) == 1); + Assert.assertTrue(sync(set.add("c")) == 1); + Assert.assertTrue(sync(set.add("d")) == 1); + Assert.assertTrue(sync(set.add("e")) == 1); + Assert.assertTrue(sync(set.add("f")) == 1); + Assert.assertTrue(sync(set.add("g")) == 1); + + MatcherAssert.assertThat(sync(set.lexRangeTail("c", false)), Matchers.contains("d", "e", "f", "g")); + MatcherAssert.assertThat(sync(set.lexRangeTail("c", true)), Matchers.contains("c", "d", "e", "f", "g")); + } + + + @Test + public void testLexRangeHead() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + sync(set.add("a")); + sync(set.add("b")); + sync(set.add("c")); + sync(set.add("d")); + sync(set.add("e")); + sync(set.add("f")); + sync(set.add("g")); + + MatcherAssert.assertThat(sync(set.lexRangeHead("c", false)), Matchers.contains("a", "b")); + MatcherAssert.assertThat(sync(set.lexRangeHead("c", true)), Matchers.contains("a", "b", "c")); + } + + + @Test + public void testLexRange() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + sync(set.add("a")); + sync(set.add("b")); + sync(set.add("c")); + sync(set.add("d")); + sync(set.add("e")); + sync(set.add("f")); + sync(set.add("g")); + + MatcherAssert.assertThat(sync(set.lexRange("aaa", true, "g", false)), Matchers.contains("b", "c", "d", "e", "f")); + } + + @Test + public void testLexCount() { + RLexSortedSetReactive set = redisson.getLexSortedSet("simple"); + sync(set.add("a")); + sync(set.add("b")); + sync(set.add("c")); + sync(set.add("d")); + sync(set.add("e")); + sync(set.add("f")); + sync(set.add("g")); + + Assert.assertEquals(5, (int)sync(set.lexCount("b", true, "f", true))); + Assert.assertEquals(3, (int)sync(set.lexCount("b", false, "f", false))); + } + +}