Skip to content

Commit ab01448

Browse files
committed
Query: sort using Comparator
1 parent 4b4d172 commit ab01448

File tree

3 files changed

+54
-19
lines changed

3 files changed

+54
-19
lines changed

objectbox-java/src/main/java/io/objectbox/query/Query.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.objectbox.query;
22

3+
import java.util.Collections;
4+
import java.util.Comparator;
35
import java.util.Date;
46
import java.util.Iterator;
57
import java.util.List;
@@ -75,16 +77,19 @@ native static void nativeSetParameters(long handle, int propertyId, String param
7577
private final QueryPublisher<T> publisher;
7678
private final List<EagerRelation> eagerRelations;
7779
private final QueryFilter<T> filter;
80+
private final Comparator<T> comparator;
7881
long handle;
7982

80-
Query(Box<T> box, long queryHandle, boolean hasOrder, List<EagerRelation> eagerRelations, QueryFilter<T> filter) {
83+
Query(Box<T> box, long queryHandle, boolean hasOrder, List<EagerRelation> eagerRelations, QueryFilter<T> filter,
84+
Comparator<T> comparator) {
8185
this.box = box;
8286
store = box.getStore();
8387
handle = queryHandle;
8488
this.hasOrder = hasOrder;
8589
publisher = new QueryPublisher<>(this, box);
8690
this.eagerRelations = eagerRelations;
8791
this.filter = filter;
92+
this.comparator = comparator;
8893
}
8994

9095
@Override
@@ -108,7 +113,7 @@ public synchronized void close() {
108113
*/
109114
@Nullable
110115
public T findFirst() {
111-
ensureNoFilter();
116+
ensureNoFilterNoComparator();
112117
return store.callInReadTx(new Callable<T>() {
113118
@Override
114119
public T call() {
@@ -120,11 +125,19 @@ public T call() {
120125
});
121126
}
122127

123-
private void ensureNoFilter() {
128+
private void ensureNoFilterNoComparator() {
124129
if (filter != null) {
125130
throw new UnsupportedOperationException("Does not yet work with a filter yet. " +
126131
"At this point, only find() and forEach() are supported with filters.");
127132
}
133+
ensureNoComparator();
134+
}
135+
136+
private void ensureNoComparator() {
137+
if (comparator != null) {
138+
throw new UnsupportedOperationException("Does not yet work with a sorting comparator yet. " +
139+
"At this point, only find() is supported with sorting comparators.");
140+
}
128141
}
129142

130143
/**
@@ -134,7 +147,7 @@ private void ensureNoFilter() {
134147
*/
135148
@Nullable
136149
public T findUnique() {
137-
ensureNoFilter();
150+
ensureNoFilterNoComparator();
138151
return store.callInReadTx(new Callable<T>() {
139152
@Override
140153
public T call() {
@@ -166,6 +179,9 @@ public List<T> call() throws Exception {
166179
}
167180
}
168181
resolveEagerRelations(entities);
182+
if (comparator != null) {
183+
Collections.sort(entities, comparator);
184+
}
169185
return entities;
170186
}
171187
});
@@ -176,7 +192,7 @@ public List<T> call() throws Exception {
176192
*/
177193
@Nonnull
178194
public List<T> find(final long offset, final long limit) {
179-
ensureNoFilter();
195+
ensureNoFilterNoComparator();
180196
return store.callInReadTx(new Callable<List<T>>() {
181197
@Override
182198
public List<T> call() {
@@ -191,7 +207,7 @@ public List<T> call() {
191207
/**
192208
* Very efficient way to get just the IDs without creating any objects. IDs can later be used to lookup objects
193209
* (lookups by ID are also very efficient in ObjectBox).
194-
*
210+
* <p>
195211
* Note: a filter set with {@link QueryBuilder#filter} will be silently ignored!
196212
*/
197213
@Nonnull
@@ -211,7 +227,7 @@ public long[] call(long cursorHandle) {
211227
* Find all Objects matching the query without actually loading the Objects. See @{@link LazyList} for details.
212228
*/
213229
public LazyList<T> findLazy() {
214-
ensureNoFilter();
230+
ensureNoFilterNoComparator();
215231
return new LazyList<>(box, findIds(), false);
216232
}
217233

@@ -225,6 +241,7 @@ public LazyList<T> findLazy() {
225241
* Note: because the consumer is called within a read transaction it may not write to the database.
226242
*/
227243
public void forEach(final QueryConsumer<T> consumer) {
244+
ensureNoComparator();
228245
box.getStore().runInReadTx(new Runnable() {
229246
@Override
230247
public void run() {
@@ -258,7 +275,7 @@ public void run() {
258275
*/
259276
@Nonnull
260277
public LazyList<T> findLazyCached() {
261-
ensureNoFilter();
278+
ensureNoFilterNoComparator();
262279
return new LazyList<>(box, findIds(), true);
263280
}
264281

objectbox-java/src/main/java/io/objectbox/query/QueryBuilder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.objectbox.query;
22

33
import java.util.ArrayList;
4+
import java.util.Comparator;
45
import java.util.Date;
56
import java.util.List;
67

@@ -78,6 +79,8 @@ enum Operator {
7879

7980
private QueryFilter<T> filter;
8081

82+
private Comparator<T> comparator;
83+
8184
private static native long nativeCreate(long storeHandle, String entityName);
8285

8386
private static native void nativeDestroy(long handle);
@@ -159,7 +162,7 @@ public Query<T> build() {
159162
throw new IllegalStateException("Incomplete logic condition. Use or()/and() between two conditions only.");
160163
}
161164
long queryHandle = nativeBuild(handle);
162-
Query<T> query = new Query<>(box, queryHandle, hasOrder, eagerRelations, filter);
165+
Query<T> query = new Query<>(box, queryHandle, hasOrder, eagerRelations, filter, comparator);
163166
close();
164167
return query;
165168
}
@@ -215,6 +218,11 @@ public QueryBuilder<T> order(Property property, int flags) {
215218
return this;
216219
}
217220

221+
public QueryBuilder<T> sort(Comparator<T> comparator) {
222+
this.comparator = comparator;
223+
return this;
224+
}
225+
218226
/**
219227
* Specifies relations that should be resolved eagerly.
220228
* This prepares the given relation objects to be preloaded (cached) avoiding further get operations from the db.

tests/objectbox-java-test/src/main/java/io/objectbox/query/QueryTest.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,16 @@
2020
import org.junit.Test;
2121

2222
import java.util.ArrayList;
23+
import java.util.Comparator;
2324
import java.util.List;
2425

2526
import io.objectbox.AbstractObjectBoxTest;
2627
import io.objectbox.Box;
2728
import io.objectbox.TestEntity;
2829
import io.objectbox.query.QueryBuilder.StringOrder;
2930

30-
31-
import static io.objectbox.TestEntity_.simpleBoolean;
32-
import static io.objectbox.TestEntity_.simpleFloat;
33-
import static io.objectbox.TestEntity_.simpleInt;
34-
import static io.objectbox.TestEntity_.simpleLong;
35-
import static io.objectbox.TestEntity_.simpleShort;
36-
import static io.objectbox.TestEntity_.simpleString;
37-
import static org.junit.Assert.assertEquals;
38-
import static org.junit.Assert.assertNotNull;
39-
import static org.junit.Assert.assertNull;
31+
import static io.objectbox.TestEntity_.*;
32+
import static org.junit.Assert.*;
4033

4134
public class QueryTest extends AbstractObjectBoxTest {
4235

@@ -422,6 +415,23 @@ public void testFindWithFilter() {
422415
assertEquals("banana milk shake", entities.get(1).getSimpleString());
423416
}
424417

418+
@Test
419+
public void testFindWithComparator() {
420+
putTestEntitiesStrings();
421+
List<TestEntity> entities = box.query().sort(new Comparator<TestEntity>() {
422+
@Override
423+
public int compare(TestEntity o1, TestEntity o2) {
424+
return o1.getSimpleString().substring(1).compareTo(o2.getSimpleString().substring(1));
425+
}
426+
}).build().find();
427+
assertEquals(5, entities.size());
428+
assertEquals("banana", entities.get(0).getSimpleString());
429+
assertEquals("banana milk shake", entities.get(1).getSimpleString());
430+
assertEquals("bar", entities.get(2).getSimpleString());
431+
assertEquals("foo bar", entities.get(3).getSimpleString());
432+
assertEquals("apple", entities.get(4).getSimpleString());
433+
}
434+
425435
private QueryFilter<TestEntity> createTestFilter() {
426436
return new QueryFilter<TestEntity>() {
427437
@Override

0 commit comments

Comments
 (0)