Skip to content

Latest commit

 

History

History
206 lines (168 loc) · 8.28 KB

File metadata and controls

206 lines (168 loc) · 8.28 KB

Query and Queryable

Contents

What it is

Query (and the Queryable wrapper) is an alternative to Streams. In other words it is an implementation of Map/Reduce based on the naming style of MS Linq.

Comparison vs. Streams

Here is an example of filtering a list of numbers for only even numbers, sorted in reverse order:

Integer[] numbers = Range.get(1, 20);
Integer[] evenQueryNumbers = Query.where(numbers, n -> n % 2 == 0).orderBy(OrderBy.Order.Descending, n -> n)
    .asArray();

snippet source | anchor

Here is the exact same function but using Java Streams:

Integer[] evenStreamNumbers = Arrays.stream(numbers).filter(n -> n % 2 == 0)
    .sorted((o1, o2) -> o2.compareTo(o1)).toArray(Integer[]::new);

snippet source | anchor

Another example using sum() vs. reduce():

String[] names = {"Llewellyn", "Scott"};
int lengthsFromQuery = Query.sum(names, n -> n.length()).intValue();

snippet source | anchor

Here is the exact same function but using Java Streams:

int lengthsFromStream = (int) Arrays.stream(names).map(n -> n.length()).reduce(0, (a, b) -> a + b);

snippet source | anchor

Other benefits

  • Simpler interface
  • Queryable extends List
  • Queryable is customizable
  • Uses SQL syntax

Queryable extends List

Another advantage of Query and Queryable is that Queryable extends List. Here is an example of converting an Array of Integers to Strings:

Using Query:

List<String> strings = Query.select(numbers, n -> "" + n);

snippet source | anchor

Using Streams:

List<String> strings2 = Arrays.stream(numbers).map(n -> "" + n).collect(Collectors.toList());

snippet source | anchor

API

SelectMany

SelectMany allows you to flatten query results.

For example:

If each element of your SELECT statement is a List you would get back a List<List>. If you would like to flatten that into a List, the easiest way is to do a Query.selectMany().

SelectMany vs SelectManyArray

Because of the limitations of the Java language, we could not override the function to allow you to return either a list or an array in your query. As a workaround we overrode the name, so if you are returning a String[] you would need to call selectManyArray.

Example:

The following code extracts the words from the following sentences, and orders them alphabetically:

Queryable<String> names = Queryable.as("Now is the time", "Fourscore and seven years ago",
    "When in the course of human events");
Queryable<String> allNames = names.selectMany(n -> Arrays.asList(n.split(" "))).orderBy(n -> n);

snippet source | anchor

resulting in

[0] = Fourscore
[1] = Now
[2] = When
[3] = ago
[4] = and
[5] = course
[6] = events
[7] = human
[8] = in
[9] = is
[10] = of
[11] = seven
[12] = the
[13] = the
[14] = time
[15] = years

snippet source | anchor

GroupBy

Here is a simple example of grouping words by their first letter.

Queryable<String> words = Queryable.as("Jack", "and", "Jill", "jumped", "up", "the", "hill");
Queryable<Entry<Character, Queryable<String>>> result = words.groupBy(w -> w.toLowerCase().charAt(0));

snippet source | anchor

producing:

[0] = j=[Jack, Jill, jumped]
[1] = a=[and]
[2] = u=[up]
[3] = t=[the]
[4] = h=[hill]

snippet source | anchor

Full transforms

In a group by, you can select both how the key is selected and how each object for the key is selected, as well as how the final list is transformed.

Here is an example of doing all three to count the number of words of the same length:

Queryable<String> words = Queryable.as("One Fish Two Fish Red Fish Blue Fish".split(" "));
Queryable<Entry<Object, Object>> result = words.groupBy(w -> w.length(), w -> w.toLowerCase(),
    r -> r.join("_"));

snippet source | anchor

resulting in

3 = one_two_red
4 = fish_fish_fish_blue_fish

snippet source | anchor

HowTos


Back to User Guide