Overview

Collection Query

This is Java6 compatible library greatly inspired By Microsoft's LINQ for Objects and Java8's collection streams. It allows doing different stuff with collections in stream fashion, like filter half of objects and select their's name, both in single line of code.

Project's javadoc

Build Status

Basically it is both:

  • LINQ for Java
  • collection streams for JDK 6

Not literally, API isn't same, but general approach is similar.

Warning!!!! please update to version 0.2.9 previous versions had huge bug inside toArray() function

Short example:

List<Person> people = ...;
List<String> names = Queryable.from(people).filter(p->p.age>20).map(p->o.name).toList();

or bit formated:

List<String> names = Queryable.from(people)
                                    .filter(p->p.age>20)
                                    .map   (p->p.name)
                                    .toList();

You may notice that I've used Lambda notion, introduced in Java 8, but I'm claiming that this lib is JDK 8 compatible, what's the deal? It's actually binary compatible with JDK86, but source compatible with JDK8. That fancy Lambdas are only syntatic sugar over interfaces and I'm using utilty Retrolambda to back-port JDK8 code.

In few words: Library is written using Java8 syntax, but can be used on JDK6 with it's old syntax, but you can also use Retrolambda and Java8 syntax.

List<String> names = Queryable.from(people)
                                    .filter(new Predicate<Person>() {
                                                public boolean filter(Person p) {
                                                    return p.age>20;
                                                }
                                            })
                                    .map   (new Converter<Person,String>() {
                                                public Integer convert(Person p) {
                                                    return p.name;
                                                }
                                            })
                                    .toList();

As you can see Java6 syntax actually kills almost all reasons to use project, as code becomes ugly and hardly written. Thankfully modern IDEs helps to generate interface implementation stuff and even collapses almost all code. Even working with old syntax will save you lot of time from writing loops and different operations inside.

Workflow

  1. Wrap your collection into queryable
  2. Do any stream operations
  3. Get result as List/array(Object[]) or iterate result in for loop.

How to use in your project

Library is available from Maven Central Reository, to use it with maven simply add following code to your's dependency section of pom.xml

<dependency>
   <groupId>com.innahema</groupId>
   <artifactId>collections-query</artifactId>
   <version>0.2.9</version>
</dependency>

if you are using Gradle than you can use following code

repositories {
    mavenCentral()
}
dependencies {
    compile 'com.innahema:collections-query:0.2.9'
}

This will allow you to use classical syntax (or use new syntax with java8).

If you would like to use Lambdas in your project You'll have to use Retrolambda, AFAIK it has limited Maven support -- you can us it, but configuration is tricky. It also can be used with Ant by adding additional task and super easily used with Gradle, thanks to gradle-retrolambda plugin.

Using gradle-retrolambda

If you would like to use fancy new Syntax you will need following:

  1. IDE with Java8 support
  2. JDK8 preview (https://jdk8.java.net/download.html )
  3. Configure Environment variables
    • JAVA6_HOME or JAVA7_HOME -- this one will be build target and will run Unit Tests
    • JAVA8_HOME -- This one will be used as compiler

If your default java is Java8 than you can only set JAVA6_HOME, in opposite, if default is 7 or 6, than you have to set JAVA8_HOME. But you can not set any variables and just set paths in gradle script, see example below.

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'me.tatarka:gradle-retrolambda:1.1.1'
        // any other plugins you need
    }
}

repositories {
    mavenCentral()
}

apply plugin: 'java'
apply plugin: 'retrolambda'


dependencies {
    compile 'com.innahema:collections-query:0.2.9'
    // any other libs you  need
}

retrolambda {    // configuration of retrolambda plugin
    jdk "C:\\Program Files (x86)\\Java\\jdk1.8.0"// path to jdk 8
    oldJdk "C:\\Program Files (x86)\\Java\\jdk1.6.0_38"
    javaVersion JavaVersion.VERSION_1_6   // target bytecode version, can be VERSION_1_7, default is 1.6
}

If you have Enviroment variables set up, then you don't have to specify this configuration parameters, just use:

retrolambda {
    javaVersion JavaVersion.VERSION_1_6   // target bytecode version, can be VERSION_1_7
}

you also can create file gradle.properties, which will not be commited to repository and will contain your local configuration. Then put in it following line

retrolambda.jdk6="C:/Program Files (x86)/Java/jdk1.6.0_38"

and use it as variable in Gradle script

retrolambda {
    oldJdk project.getProperty('retrolambda.jdk6')
}

For more details see description of gradle-retrolambda.

Changelog

Upcoming (SNAPSHOT)

  • Breaking changes: Removed Converter interface, using Function1 for map method
  • Exception handling

0.2.9

  • fixed toArray() issue : element at point of resize wasn't added

0.2.8

  • fixed methods to work with primitive arrays

0.2.7

  • fixed toArray() polymorphic issue. If array elements had different type, method was throwing ArrayStoreException
  • ArrayIterator performance improvement
  • ArrayIterator_*** for arrays of primitive types (byte[], int[], etc. )
  • hooray, 100% test coverage!