Boon Sorting
Boon Home | Boon Source | If you are new to boon, you might want to start here. Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!
Java Boon - Boon Sorting for Java, JSON and Java collections
Many languages have built in support to easily sort lists, maps, JSON and Java objects. Boon adds this to Java.
Boon Sorting Java objects, lists/maps and JSON
Boon allows you to easily sort Java instances or Maps/Lists or JSON.
Let's get a bird's eye view....
sort, sortBy, sortNullFirst, sortDesc (natural and property sort)
sort(employees); //Sort the employees in natural order (works with arrays, lists, sets, iterable)
sort( employees, "lastName"); //Sorts the employees by last name
sort( departmentList ); //Sorts the department by natural sort order
sort( employees, sortBy( "department.name" ),
sortByDescending( "lastName" ),
sortBy( "firstName" ) ); //Works with lists, collections, sets, arrays, iterable
sort(employees,
sortBy("contactInfo.phoneNumbers[0]")); //Sort by path expression. This is very powerful!
sort(employees,
sortByDescending("contactInfo.phoneNumbers[0]"); //Sorts by path expression. Descending
There are many flavors of sorts, there is sort, sortNullFirst, sortDesc, sortDescNullsFirst, and they work with Iterable, List, Collection and array. There is even a version of sort that allows every field to be sorted in a different manner (ascending null first, descending null last, and so on). You can sort by properties or property paths. You can also sort JSON, List/Maps or Java instances (POJOs) all from Boon. It is truly awesome!
Boon is all about convention over configuration and complicated documentation. For example, the sorting of text always uses collation so you will not get weird garbage. It you specify "this" as property name or you don't specify a property or property path, then the object will be sorted using natural sort order which means the object will be sorted by comparable or if the object does not implement comparable then it will be sorted based on a sortable field names like "name", "orderBy", "title", or a property or field ending in "Name", or the first basic comparable type found in the object. Boon follows the ideology of convention over configuration. Lastly if no suitable natural sort key can be found Boon throws an exception. In practice, it just works! We have an example of sorting an object using a natural sort but without the object being comparable.
min, max, greatest, least, and more
Boon allows you to easily perform the following operations and these build on top of Boon sorting capabilities.
max(employees); //Sort employees and return the highest by natural order.
greatest(employees, 5); //Return the highest five employees by natural sort order.
min(employees); //Sort employees and return the lowest employee by natural sort order.
least(employees, 5); //Sort the employees and return the lowest five employees by natural sort order.
max(employees, "salary"); //Return the employee with the maximum salary
greatest(employees, "salary", 5); //Return the top five salaried employees
min(employees, "salary"); //get the lowest paid employee
least(employees, "salary", 5); //get the lowest five employees
search(employees, employee); //find an employee
int index = searchForIndex(employees, employee); //find the position of the employee in the list
Boon also has a full in-memory database like utility called data repo that allows you to sort using Java collections as indexes. Boon also has a filtering library. Those are covered in other Boon documents. Boon has a lot of useful features. It is more than the sum of its parts.
Let's set up an example:
First lets create a few test objects:
static List<Department> departmentsList = list(
new Department("Engineering").add(
new Employee(1, 100, "Rick", "Hightower", "555-555-1000"),
new Employee(2, 200, "John", "Smith", "555-555-1215", "555-555-1214", "555-555-1213"),
new Employee(3, 300, "Drew", "Donaldson", "555-555-1216"),
new Employee(4, 400, "Nick", "LaySacky", "555-555-1217")
),
new Department("HR").add(
new Employee(5, 100, "Dianna", "Hightower", "555-555-1218"),
new Employee(6, 200, "Derek", "Smith", "555-555-1219"),
new Employee(7, 300, "Tonya", "Donaldson", "555-555-1220"),
new Employee(8, 400, "Sue", "LaySacky", "555-555-9999")
), new Department("Manufacturing").add(),
new Department("Sales").add(),
new Department("Marketing").add()
);
Boon will happily sort domain object like the above, but Boon will also happily sort lists and maps, etc. Boon has added simple utility functions to make the creation of Maps and Lists easy.
static List<?> departmentObjects = list(
map("name", "Engineering",
"employees", list(
map("id", 1, "salary", 100, "firstName", "Rick", "lastName", "Hightower",
"contactInfo", map("phoneNumbers",
list("555-555-0000")
)
),
map("id", 2, "salary", 200, "firstName", "John", "lastName", "Smith",
"contactInfo", map("phoneNumbers", list("555-555-1215",
"555-555-1214", "555-555-1213"))),
map("id", 3, "salary", 300, "firstName", "Drew", "lastName", "Donaldson",
"contactInfo", map("phoneNumbers", list("555-555-1216"))),
map("id", 4, "salary", 400, "firstName", "Nick", "lastName", "LaySacky",
"contactInfo", map("phoneNumbers", list("555-555-1217")))
)
),
map("name", "HR",
"employees", list(
map("id", 5, "salary", 100, "firstName", "Dianna", "lastName", "Hightower",
"contactInfo",
map("phoneNumbers", list("555-555-1218"))),
map("id", 6, "salary", 200, "firstName", "Derek", "lastName", "Smith",
"contactInfo",
map("phoneNumbers", list("555-555-1219"))),
map("id", 7, "salary", 300, "firstName", "Tonya", "lastName", "Donaldson",
"contactInfo", map("phoneNumbers", list("555-555-1220"))),
map("id", 8, "salary", 400, "firstName", "Sue", "lastName", "LaySacky",
"contactInfo", map("phoneNumbers", list("555-555-9999")))
)
),
map("name", "Manufacturing", "employees", Collections.EMPTY_LIST),
map("name", "Sales", "employees", Collections.EMPTY_LIST),
map("name", "Marketing", "employees", Collections.EMPTY_LIST)
);
Object jsonObject = fromJson(json);
List<?> jsonDepartments = (List<?>) jsonObject;
List<?> jsonEmployees = (List<Employee>) atIndex(jsonDepartments, "employees");
Here is the JSON that we will be working with:
[
{
"name": "Engineering",
"employees": [
{
"id": 1,
"salary": 100,
"firstName": "Rick",
"lastName": "Hightower",
"contactInfo": {
"phoneNumbers": [
"555-555-0000"
]
}
},
{
"id": 2,
"salary": 200,
"firstName": "John",
"lastName": "Smith",
"contactInfo": {
"phoneNumbers": [
"555-555-1215",
"555-555-1214",
"555-555-1213"
]
}
},
{
"id": 3,
"salary": 300,
"firstName": "Drew",
"lastName": "Donaldson",
"contactInfo": {
"phoneNumbers": [
"555-555-1216"
]
}
},
{
"id": 4,
"salary": 400,
"firstName": "Nick",
"lastName": "LaySacky",
"contactInfo": {
"phoneNumbers": [
"555-555-1217"
]
}
}
]
},
{
"name": "HR",
"employees": [
{
"id": 5,
"salary": 100,
"firstName": "Dianna",
"lastName": "Hightower",
"contactInfo": {
"phoneNumbers": [
"555-555-1218"
]
}
},
{
"id": 6,
"salary": 200,
"firstName": "Derek",
"lastName": "Smith",
"contactInfo": {
"phoneNumbers": [
"555-555-1219"
]
}
},
{
"id": 7,
"salary": 300,
"firstName": "Tonya",
"lastName": "Donaldson",
"contactInfo": {
"phoneNumbers": [
"555-555-1220"
]
}
},
{
"id": 8,
"salary": 400,
"firstName": "Sue",
"lastName": "LaySacky",
"contactInfo": {
"phoneNumbers": [
"555-555-9999"
]
}
}
]
},
{
"name": "Manufacturing",
"employees": [
]
},
{
"name": "Sales",
"employees": [
]
},
{
"name": "Marketing",
"employees": [
]
}
]
First let's cover the java
List<Employee> employees = (List<Employee>) atIndex(departmentsList, "employees");
Now we can start working with the employees. Note that puts works like Ruby puts, and putl is like puts but it puts each object on a newline. (The atIndex method uses a boon path expression to grab every employee from every department, read the short tutorial on boon path expression or just trust me that this does what I said or just assume employees is a list of employees).
putl ( "Max employee by natural order",
max(employees) );
putl ( "Greatest top 5 employee by natural order",
greatest(employees, 5) );
putl ( "Min employee by natural order",
min(employees) );
putl ( "Least top 5 employee by natural order",
least(employees, 5) );
putl ( "Who makes the most?",
max(employees, "salary") );
putl ( "Who are the top five earners?",
greatest(employees, "salary", 5) );
putl ( "Who makes the least?",
min(employees, "salary") );
putl ( "Who are the lowest paid?",
least(employees, "salary", 5) );
sort(employees);
sort( employees, "lastName");
putl( "Sorted employees by lastName", employees);
sort( departmentList );
putl( "Sorted department in natural order", departmentList);
sort( employees, sortBy( "department.name" ),
sortByDescending( "lastName" ),
sortBy( "firstName" ) );
putl("Sort employees by department name, descending lastName and" +
" ascending firstName", employees);
sort(employees,
sortBy("contactInfo.phoneNumbers[0]"));
putl("Sort by phone numbers", employees);
sort( employees,
sortByDescending("contactInfo.phoneNumbers[0]") );
putl("Sort by phone numbers descending", employees);
The above begets the following output:
Max employee by natural order
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Greatest top 5 employee by natural order (natural order for employees is sort by first name)
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Min employee by natural order
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Least top 5 employee by natural order
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Who makes the most? (sort on salary)
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Who are the top five earners?
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Who makes the least?
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Who are the lowest paid?
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Sorted employees by lastName
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Sorted department in natural order
Department{name='Engineering', employees=[1, 2, 3, 4]}
Department{name='HR', employees=[5, 6, 7, 8]}
Department{name='Manufacturing', employees=[]}
Department{name='Marketing', employees=[]}
Department{name='Sales', employees=[]}
Sort employees by department name, descending lastName and ascending firstName
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Sort by phone numbers
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Sort by phone numbers descending
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Working with List/Map and JSON
You can easily sort list of maps and this works out well for JSON objects which can be read in easily and readily as list of maps (Boon ships with the fastest known JSON parser on the JVM--Yep faster that the one your thinking of, and quite a few you never heard of and that other one that is spelled funny too).
Working with lists of maps
List<?> employeeObjects = (List<?>) atIndex(departmentObjects, "employees");
Working with json list of maps
Object jsonObject = fromJson(json);
List<?> jsonDepartments = (List<?>) jsonObject;
List<?> jsonEmployees = (List<Employee>) atIndex(jsonDepartments, "employees");
The sorting code is the same as before.
Now here is the output:
______________________________ From LIST MAPS ______________________________
Who makes the most?
{id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}
Who are the top five earners?
{id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}
{id=8, salary=400, firstName=Sue, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-9999]}}
{id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}
{id=7, salary=300, firstName=Tonya, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1220]}}
{id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}
Who makes the least?
{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}
Who are the lowest paid?
{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}
{id=5, salary=100, firstName=Dianna, lastName=Hightower, contactInfo={phoneNumbers=[555-555-1218]}}
{id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}
{id=6, salary=200, firstName=Derek, lastName=Smith, contactInfo={phoneNumbers=[555-555-1219]}}
{id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}
Sorted employees by lastName
{id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}
{id=7, salary=300, firstName=Tonya, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1220]}}
{id=5, salary=100, firstName=Dianna, lastName=Hightower, contactInfo={phoneNumbers=[555-555-1218]}}
{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}
{id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}
{id=8, salary=400, firstName=Sue, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-9999]}}
{id=6, salary=200, firstName=Derek, lastName=Smith, contactInfo={phoneNumbers=[555-555-1219]}}
{id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}
Sorted department in natural order
{name=Engineering, employees=[{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}, {id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}, {id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}, {id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}]}
{name=HR, employees=[{id=5, salary=100, firstName=Dianna, lastName=Hightower, contactInfo={phoneNumbers=[555-555-1218]}}, {id=6, salary=200, firstName=Derek, lastName=Smith, contactInfo={phoneNumbers=[555-555-1219]}}, {id=7, salary=300, firstName=Tonya, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1220]}}, {id=8, salary=400, firstName=Sue, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-9999]}}]}
{name=Manufacturing, employees=[]}
{name=Sales, employees=[]}
{name=Marketing, employees=[]}
Sort by phone numbers
{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}
{id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}
{id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}
{id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}
{id=5, salary=100, firstName=Dianna, lastName=Hightower, contactInfo={phoneNumbers=[555-555-1218]}}
{id=6, salary=200, firstName=Derek, lastName=Smith, contactInfo={phoneNumbers=[555-555-1219]}}
{id=7, salary=300, firstName=Tonya, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1220]}}
{id=8, salary=400, firstName=Sue, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-9999]}}
Sort by phone numbers descending
{id=8, salary=400, firstName=Sue, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-9999]}}
{id=7, salary=300, firstName=Tonya, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1220]}}
{id=6, salary=200, firstName=Derek, lastName=Smith, contactInfo={phoneNumbers=[555-555-1219]}}
{id=5, salary=100, firstName=Dianna, lastName=Hightower, contactInfo={phoneNumbers=[555-555-1218]}}
{id=4, salary=400, firstName=Nick, lastName=LaySacky, contactInfo={phoneNumbers=[555-555-1217]}}
{id=3, salary=300, firstName=Drew, lastName=Donaldson, contactInfo={phoneNumbers=[555-555-1216]}}
{id=2, salary=200, firstName=John, lastName=Smith, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}}
{id=1, salary=100, firstName=Rick, lastName=Hightower, contactInfo={phoneNumbers=[555-555-0000]}}
______________________________ From JSON ______________________________
Who makes the most?
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
Who are the top five earners?
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
{id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
{id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
Who makes the least?
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
Who are the lowest paid?
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
{id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
Sorted employees by lastName
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
{id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
{id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
{id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}
Sorted department in natural order
{employees=[{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}, {id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}, {id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}, {id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}], name=Engineering}
{employees=[{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}, {id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}, {id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}, {id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}], name=HR}
{employees=[], name=Manufacturing}
{employees=[], name=Sales}
{employees=[], name=Marketing}
Sort employees by department name, descending lastName and ascending firstName
{id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
{id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}
{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
{id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}
Sort by phone numbers
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}
{id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}
{id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}
{id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}
Sort by phone numbers descending
{id=8, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-9999]}, firstName=Sue}
{id=7, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1220]}, firstName=Tonya}
{id=6, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1219]}, firstName=Derek}
{id=5, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-1218]}, firstName=Dianna}
{id=4, lastName=LaySacky, salary=400, contactInfo={phoneNumbers=[555-555-1217]}, firstName=Nick}
{id=3, lastName=Donaldson, salary=300, contactInfo={phoneNumbers=[555-555-1216]}, firstName=Drew}
{id=2, lastName=Smith, salary=200, contactInfo={phoneNumbers=[555-555-1215, 555-555-1214, 555-555-1213]}, firstName=John}
{id=1, lastName=Hightower, salary=100, contactInfo={phoneNumbers=[555-555-0000]}, firstName=Rick}
Binary search
//Using Search
sort(employees);
Employee employee = employees.get(5);
Employee employee2 = search(employees, employee);
int index = searchForIndex(employees, employee);
putl("This employee was found at ", index, employee2, employee, '\n', employees);
Now let's see the output from the search.
This employee was found at
5
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Works with arrays, iterable and all sorts of fun stuff
Boon can work with Lists (which I prefer for sorting), but it can also work with arrays, collections, and iterables.
Sorting a set
Set<Employee> employeesSet = new LinkedHashSet<>(employees);
employeesSet = (Set<Employee>) sort(Employee.class, employeesSet, "id");
putl("Sort Employee SET by id", employeesSet);
Sort Employee SET by id
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Sorting an array
Employee[] employeesArray = toArray(Employee.class, employees);
sort(employeesArray, "firstName");
putl("Sort Employee ARRAY by firstName", employeesArray);
Note Boon has a utility function that converts any collection into an array called toArray. So first we create the employees list into an array and then we sort it by firstName and print out the results with putl.
Sort Employee ARRAY by firstName
Employee{id=6, salary=200, department=HR, phone number=555-555-1219, firstName='Derek', lastName='Smith'}
Employee{id=5, salary=100, department=HR, phone number=555-555-1218, firstName='Dianna', lastName='Hightower'}
Employee{id=3, salary=300, department=Engineering, phone number=555-555-1216, firstName='Drew', lastName='Donaldson'}
Employee{id=2, salary=200, department=Engineering, phone number=555-555-1215, firstName='John', lastName='Smith'}
Employee{id=4, salary=400, department=Engineering, phone number=555-555-1217, firstName='Nick', lastName='LaySacky'}
Employee{id=1, salary=100, department=Engineering, phone number=555-555-1000, firstName='Rick', lastName='Hightower'}
Employee{id=8, salary=400, department=HR, phone number=555-555-9999, firstName='Sue', lastName='LaySacky'}
Employee{id=7, salary=300, department=HR, phone number=555-555-1220, firstName='Tonya', lastName='Donaldson'}
model objects / classes for this example
public class ContactInfo {
String address;
List<String> phoneNumbers;
}
public class Employee implements Comparable<Employee> {
int id;
int salary;
String firstName;
String lastName;
ContactInfo contactInfo = new ContactInfo();
Department department;
public Employee(int id, int salary, String firstName, String lastName,
String... phoneNumbers) {
this.id = id;
this.salary = salary;
this.firstName = firstName;
this.lastName = lastName;
for (String phone : phoneNumbers) {
contactInfo.phoneNumbers = lazyAdd(contactInfo.phoneNumbers, phone);
}
}
...//left off getter / setter / equals and hashCode
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", salary=" + salary +
", department=" + (department == null ? "NONE" : department.getName()) +
", phone number=" + atIndex (this, "contactInfo.phoneNumbers[0]") +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
"}";
}
@Override
public int compareTo(Employee otherEmployee) {
return this.firstName.compareTo(otherEmployee.firstName);
}
public void setDepartment(Department department) {
this.department = department;
}
}
//Notice that Department is not comparable but boon found and used the name property to make it have
// a "natural" sort order.
public class Department {
private String name;
private List<Employee> employees;
public Department() {
}
public Department(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department add(Employee... employees) {
for (Employee employee : employees) {
employee.setDepartment(this);
}
this.employees = lazyAdd(this.employees, employees);
return this;
}
... //left off getter / setters equals and friends
@Override
public String toString() {
return "Department{" +
"name='" + name + '\'' +
", employees=" + atIndex(employees, "id") +
'}';
}
}
Complete listing for example
package com.examples;
import static org.boon.core.Conversions.toArray;
import static org.boon.sort.Sort.sortBy;
import static org.boon.sort.Sort.sortByDescending;
import static org.boon.sort.Sorting.*;
import static org.boon.sort.Ordering.*;
import org.junit.Test;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static org.boon.Boon.*;
import static org.boon.Boon.puts;
import static org.boon.Lists.lazyAdd;
import static org.boon.Lists.list;
import static org.boon.Maps.map;
import static org.boon.Ok.okOrDie;
import static org.boon.core.reflection.BeanUtils.atIndex;
import static org.boon.primitive.Chr.multiply;
public class SortingObjects {
@Test
public void test() {
SortingObjects.main();
}
public static class ContactInfo {
String address;
List<String> phoneNumbers;
}
public static class Employee implements Comparable<Employee> {
int id;
int salary;
String firstName;
String lastName;
ContactInfo contactInfo = new ContactInfo();
Department department;
public Employee() {
}
public Employee(int id, int salary, String firstName, String lastName,
String... phoneNumbers) {
this.id = id;
this.salary = salary;
this.firstName = firstName;
this.lastName = lastName;
for (String phone : phoneNumbers) {
contactInfo.phoneNumbers = lazyAdd(contactInfo.phoneNumbers, phone);
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (id != employee.id) return false;
if (salary != employee.salary) return false;
if (firstName != null ? !firstName.equals(employee.firstName) : employee.firstName != null) return false;
if (lastName != null ? !lastName.equals(employee.lastName) : employee.lastName != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + salary;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", salary=" + salary +
", department=" + (department == null ? "NONE" : department.getName()) +
", phone number=" + atIndex (this, "contactInfo.phoneNumbers[0]") +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
"}";
}
@Override
public int compareTo(Employee otherEmployee) {
return this.firstName.compareTo(otherEmployee.firstName);
}
public void setDepartment(Department department) {
this.department = department;
}
}
public static class Department {
private String name;
private List<Employee> employees;
public Department() {
}
public Department(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department add(Employee... employees) {
for (Employee employee : employees) {
employee.setDepartment(this);
}
this.employees = lazyAdd(this.employees, employees);
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Department that = (Department) o;
if (employees != null ? !employees.equals(that.employees) : that.employees != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (employees != null ? employees.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Department{" +
"name='" + name + '\'' +
", employees=" + atIndex(employees, "id") +
'}';
}
}
static List<Department> departmentsList = list(
new Department("Engineering").add(
new Employee(1, 100, "Rick", "Hightower", "555-555-1000"),
new Employee(2, 200, "John", "Smith", "555-555-1215", "555-555-1214", "555-555-1213"),
new Employee(3, 300, "Drew", "Donaldson", "555-555-1216"),
new Employee(4, 400, "Nick", "LaySacky", "555-555-1217")
),
new Department("HR").add(
new Employee(5, 100, "Dianna", "Hightower", "555-555-1218"),
new Employee(6, 200, "Derek", "Smith", "555-555-1219"),
new Employee(7, 300, "Tonya", "Donaldson", "555-555-1220"),
new Employee(8, 400, "Sue", "LaySacky", "555-555-9999")
), new Department("Manufacturing").add(),
new Department("Sales").add(),
new Department("Marketing").add()
);
static List<?> departmentObjects = list(
map("name", "Engineering",
"employees", list(
map("id", 1, "salary", 100, "firstName", "Rick", "lastName", "Hightower",
"contactInfo", map("phoneNumbers",
list("555-555-0000")
)
),
map("id", 2, "salary", 200, "firstName", "John", "lastName", "Smith",
"contactInfo", map("phoneNumbers", list("555-555-1215",
"555-555-1214", "555-555-1213"))),
map("id", 3, "salary", 300, "firstName", "Drew", "lastName", "Donaldson",
"contactInfo", map("phoneNumbers", list("555-555-1216"))),
map("id", 4, "salary", 400, "firstName", "Nick", "lastName", "LaySacky",
"contactInfo", map("phoneNumbers", list("555-555-1217")))
)
),
map("name", "HR",
"employees", list(
map("id", 5, "salary", 100, "firstName", "Dianna", "lastName", "Hightower",
"contactInfo",
map("phoneNumbers", list("555-555-1218"))),
map("id", 6, "salary", 200, "firstName", "Derek", "lastName", "Smith",
"contactInfo",
map("phoneNumbers", list("555-555-1219"))),
map("id", 7, "salary", 300, "firstName", "Tonya", "lastName", "Donaldson",
"contactInfo", map("phoneNumbers", list("555-555-1220"))),
map("id", 8, "salary", 400, "firstName", "Sue", "lastName", "LaySacky",
"contactInfo", map("phoneNumbers", list("555-555-9999")))
)
),
map("name", "Manufacturing", "employees", Collections.EMPTY_LIST),
map("name", "Sales", "employees", Collections.EMPTY_LIST),
map("name", "Marketing", "employees", Collections.EMPTY_LIST)
);
static boolean ok;
public static void main(String... args) {
puts(multiply('_', 30), "From JAVA Objects", multiply('_', 30), "\n");
List<Employee> employees = (List<Employee>) atIndex(departmentsList, "employees");
sorting(employees, departmentsList);
puts(multiply('_', 30), "From LIST MAPS", multiply('_', 30), "\n");
List<?> employeeObjects = (List<?>) atIndex(departmentObjects, "employees");
sorting(employeeObjects, departmentObjects);
puts(multiply('_', 30), "From JSON", multiply('_', 30), "\n");
String json = toJson(departmentObjects);
puts(json);
Object jsonObject = fromJson(json);
List<?> jsonDepartments = (List<?>) jsonObject;
List<?> jsonEmployees = (List<Employee>) atIndex(jsonDepartments, "employees");
sorting(jsonEmployees, jsonDepartments);
//Using Search
sort(employees);
Employee employee = employees.get(5);
Employee employee2 = search(employees, employee);
int index = searchForIndex(employees, employee);
putl("This employee was found at ", index, employee2, employee, '\n', employees);
//Using a Set instead of a list
Set<Employee> employeesSet = new LinkedHashSet<>(employees);
employeesSet = (Set<Employee>) sort(Employee.class, employeesSet, "id");
putl("Sort Employee SET by id", employeesSet);
Employee[] employeesArray = toArray(Employee.class, employees);
sort(employeesArray, "firstName");
putl("Sort Employee ARRAY by firstName", employeesArray);
}
private static void sorting(List<?> employees, List<?> departmentList) {
putl ( "Max employee by natural order",
max(employees) );
putl ( "Greatest top 5 employee by natural order",
greatest(employees, 5) );
putl ( "Min employee by natural order",
min(employees) );
putl ( "Least top 5 employee by natural order",
least(employees, 5) );
putl ( "Who makes the most?",
max(employees, "salary") );
putl ( "Who are the top five earners?",
greatest(employees, "salary", 5) );
putl ( "Who makes the least?",
min(employees, "salary") );
putl ( "Who are the lowest paid?",
least(employees, "salary", 5) );
sort(employees);
sort( employees, "lastName");
putl( "Sorted employees by lastName", employees);
sort( departmentList );
putl( "Sorted department in natural order", departmentList);
sort( employees, sortBy( "department.name" ),
sortByDescending( "lastName" ),
sortBy( "firstName" ) );
putl("Sort employees by department name, descending lastName and" +
" ascending firstName", employees);
sort(employees,
sortBy("contactInfo.phoneNumbers[0]"));
putl("Sort by phone numbers", employees);
sort( employees,
sortByDescending("contactInfo.phoneNumbers[0]") );
putl("Sort by phone numbers descending", employees);
}
}
There is a lot more to boon than this
If this piqued your interests you should read up on Boon path expressions which are used in this example. You should also read about Boon data repo which is an in-memory query engine for Java class instances and Java collections. Boon has sorting, filtering, validation, path expressions, and an in-memory query engine. Boon also supports JSON via dependency injection, JSON configuration files, JSON parsing, JSON serializing, JSON side-ways serializing for speed (read / write from arrays instead ob JSON objects), and JSON to Java call marshaling. Boon also has a handlebars based template lib. Come explore Boon.
Thoughts
Thoughts? Write me at richard high tower AT g mail dot c-o-m (Rick Hightower).
Further Reading:
If you are new to boon start here:
- Java Boon Byte Buffer Builder
- Java Boon Slice Notation
- Java Boon Slice's work with TreeSets
- Java Boon Description
- More...
- Boon Home
- Boon Source
- Introducing Boon October 2013
- Java Slice Notation
- What if Java collections were easy to search and sort?
- Boon HTTP utils
- Boon Java JSON parser Benchmarks or hell yeah JSON parsing is damn fast!
- Boon JSON parser is really damn fast! Part II
- Boon JSON parser Round III now just not fast as but much faster than other Java JSON parsers
- Boon World's fastest Java JSON parser Round IV from fast to blazing to rocket fuel aka Braggers going to brag
- Boon gets adopted by JSON Path as the default Java JSON parser
- Boon graphics showing just how fast Boon JSON parsing is - about 50% to 200% faster than the graphs shown here now so wicked fast became wickeder - just got sick of making graphics
- 10 minute guide to Boon JSON parsing after I added @JsonIgnore, @JsonProperty, @JsonView, @Exposes, etc.
- Hightower speaks to the master of Java JSON parsing, the king of speed The COW TOWN CODER!
- Boon provides easy Java objects from lists, from maps and from JSON.
Why Boon?
Easily read in files into lines or a giant string with one method call. Works with files, URLs, class-path, etc. Boon IO support will surprise you how easy it is. Boon has Slice notation for dealing with Strings, Lists, primitive arrays, Tree Maps, etc. If you are from Groovy land, Ruby land, Python land, or whatever land, and you have to use Java then Boon might give you some relief from API bloat. If you are like me, and you like to use Java, then Boon is for you too. Boon lets Java be Java, but adds the missing productive APIs from Python, Ruby, and Groovy. Boon may not be Ruby or Groovy, but its a real Boon to Java development.
Core Boon Philosophy
Core Boon will never have any dependencies. It will always be able to run as a single jar. This is not just NIH, but it is partly. My view of what Java needs is more inline with what Python, Ruby and Groovy provide. Boon is an addition on top of the JVM to make up the difference between the harder to use APIs that come with Java and the types of utilities that are built into Ruby, Python, PHP, Groovy etc. Boon is a Java centric view of those libs. The vision of Boon and the current implementation is really far apart.
Contact Info
blog|[twitter](https://twitter.com/RickHigh|[infoq]http://www.infoq.com/author/Rick-Hightower|[stackoverflow](http://stackoverflow.com/users/2876739/rickhigh)|[java lobby](http://java.dzone.com/users/rhightower)|Other | richard high tower AT g mail dot c-o-m (Rick Hightower)|work|cloud|nosql
No comments:
Post a Comment