iSortBox

Additional

Language
Java
Version
N/A
Created
Sep 23, 2017
Updated
Sep 25, 2017
Owner
Su Cong (sucong0826)
Contributor
Su Cong (sucong0826)
1
Activity
Badge
Generate
Download
Source code

Promotion

iSortBox

Summary

What is iSortBox? Just like what it says: Simplify sorting!

This framework achieves a goal which makes sorting easier, moreover, you will benefit from what it provides such as pre-processing, converting, grouping and filtering.

As the name iSortBox, the letter 'i' means input and the letter 'o' means output, as for the details on how to complete the work, all are encapsulated in iSortBox.

Design Prototype

In this chapter, some pictures about iSortBox will be posted here.

Why iSortBox?

What iSortBox tries to solve is to standardize the usage of sorting in a project. That's the aim of iSortBox. There are no advanced skills and technologies in iSortBox, instead, it just simplifies sort by encapsulating several standardized and processed steps to make you sort easily.

Therefore, iSortBox acts as a helper framework. Once you want to sort a disordered set, iSortBox will help you solve the sort issue.

iSortBox Prototype

There are two necessary parts and two optional parts in the design prototype.

The necessary parts are

  • Process (part 1)
  • Sort (part 2)

The optional parts are

  • Group (part 3)
  • Filter (part 4)

These parts are obtained through a lot of trying and analyzing. In order to complete sort, these parts are enough for developers.

Next, I will analyze each part with code and how to make full use of these parts.

Analysis

Before the analysis, I introduce a class named Student. It is used to code samples.

public class Student {
    private int id;
    private String name;
    private int age;
    private float weight;
    
    public Student(int id, String name, int age, float weight) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    
    public int getId() {
        return this.id;
    }
    
    public String getName() {
        return this.name;
    }
    
    public int getAge() {
        return this.age;
    }
    
    public float getWeight() {
        return this.weight;
    }
}

Part-1/2 Process and Sort

The part of process is going to complete several steps, it contains :

  1. Receive an input
  2. Pre-process (optional)
  3. Configure sort
  4. Find sort keys
  5. Convert
  6. Sort
  7. Sample

1.1 Receive an input

As the prototype mentioned, iSortBox needs an input entrance. Presume that there is a list of

Student.List<Student> studentList =newArrayList<>(4); studentList.add(newStudent(3, "Daniel", 14, 89.3f)); studentList.add(newStudent(1, "Larry", 13, 65.5f)); studentList.add(newStudent(20, "John", 14, 74.0f)); studentList.add(newStudent(15, "Lyn", 10, 70.2f));


Now, four students are generated. The list studentList is going to be ordered by iSortBox, Now, the list acts as input to enter the iSortBox, that is, the receiving an input.

1.2 Pre-process (Optional)

Then you may want to pre-process your input. Step 2

Pre-process will do it. In iSortBox, an interface named Process existing the package underneath sortbox.common.process undertakes the task. You can define a new interface to extend it or a new class to implement it. For example :publicclassInputListProcess implmenents Process<List<?>> { @Overridepublicvoidprocess(List<?>target, Object... args) { removeEmpty(target); } }

You can create the instance of it to be used as an argument passed into a method in SortExecutor. Anyway, this step is optional.


Use pre-process before sorting when you need.

1.3 Configure Sorting

In iSortBox, sort is regarded as sort a collection by one property or some properties.

For example, you may need the studentList to be sorted by id from 1 to N. You may need to sort the list by name from 'a' to 'z'. The actual intent of sort is to sort values on some properties.

Sort is a process to define a

Comparator. If you think that sort is as simple as defining a Comparator, why to write the iSortBox instead of using Comparator directly? If you know only one known property and use this property to sort a list, nothing different. In contrast, using Comparator directly will save lots of resources.Collections.sort(studentList, newComparator<>() { @Overridepublicintcompare(Students1, Students2) { return s1.getId() - s2.getId(); } });

However, there is a more common case, you don't know which property will be used to sort a list at all until clients or users trigger a sort by a certain property they select. Just like Excel.

Users may select the column of id to sort the studentList or select the column of name to sort.

For the cases above, developers can still use Comparator to complete the task. But iSortBox provides a more convenient way to do it.

The mechanism is reflection in Java.

First of all, iSortBox uses reflection to generate a

PropertyTable which holds the properties information of T, the Student. The PropertyTable records the name of a property, the type of a property, and the value of a property. The object is used to be searched by developers and provided to show at some UI interface for being selected by users.List<PropertyTableItem> list =newPropertyTable<Student>().check(studentList.get(0)).getPropertyList();

Or

List<PropertyTableItem> list =newPropertyTable<Student>().check(Student.class).getPropertyList();

If you only want to get the name and type of properties without concrete values, the latter is better.

Well, iSortBox gives us a table recording properties information, for developers and users, are able to specify some properties to sort a list. It's time to introduce the

SortConfig<T> class. SortConfig<T> is a manifest file.SortConfig<Student> config =newSortConfig<Student>().newBuilder() .set(1, "id", newNumberOrderComparator<>(true)) .set(2, "name", newNameComparator<>()) .combineMode(CombineMode.MULTIPLE) .useDefaultComparator(false) .build();

Please look at the code,

T is the generic type of Student which means that the configuration is provided by an instance of Student. It's easy to use Builder Pattern to build up a configuration. Now set(int priority, String propertyName, AbstractComparator<T> comparator)method is the key of the whole configuration.

  • int priority : means that the property is given to a priority when sort happens. The level in a range from 0 to N indicates the highest level to lowest level.

  • String propertyName : means that the name of a property.

    AbstractComparator<T> comparator: means that how to sort a list, it can be null.

    Well, a call to set(1, "id", new NumberOrderComparator<>(true)) means that a list will be sorted by id using NumberOrderComparator firstly.

    combineMode(CombineMode.MULTIPLE) is easy to understand. CombineMode is an enumeration class which has two instances of SINGLE and MULTIPLE.

  • SINGLE: means that users and developers can only specify one property which has the highest priority to sort a list , the others will be dropped off. However if you specify more than one properties, only one property will be kept, the one which has the highest priority. If you specify one property only but the property doesn't exist, a failed sorting but iSortBox will return you the original data list that encapsulated in SortResult.

    MULTIPLE: means that you can specify more than one properties, no amount limitation. Those you specify will be saved in a map, its key is TwoTuple<Integer, String>, its value is AbstractComparator<T>. The map is a middle variable, later, those will be handled. Here, you just need to know that MULTIPLE allows you to specify more properties.

    useDefaultComparator(boolean use) is an error compatible method. When you call set(..) and pass in a null Comparator, you can setup this method to notify iSortBox whether to enable the default comparator DefaultComparator. If you set false meanwhile comparator is null, iSortBox will return you the original data list that encapsulated in SortResult.

    When


    build() is called, an instance of SortConfig<T> will be generated.

    1.4 Find sort keys (private implementation)

    Once you specify the properties whatever you give or you select from PropertyTable, Find sort keys is an important step. iSortBox is going to pick out these properties you select then it checks whether these properties are truly existing through PropertyTable or direct reflection. After checking, the remaining properties will be put into SortKey which has the same role as PropertyTableItem.

    The result of finding sort keys is


    List<TwoTuple<T, Queue<SortKey>>>. TwoTuple<F, S> is a kind of skill that makes two objects become one object. As above, T can be regarded as the type of Student, Queue<SortKey> is a set of SortKey which holds the information of specified properties.

    1.5. Convert (private implementation)

    Before illustrating what is convert, let's familiar with a class


    SortItem<T>. This class collects a set of SortKeyand keeps an original data of T. Actually, when SortExecutor executes a sort, it sorts a list of SortItem<T>. You are maybe puzzled about this, but class SortItem<T> is a middle component as well, it belongs to the inner detail of iSortBox framework. The reason of why this class is designated in iSortBox is to complete a sort but keeps the original data.

    1.6 Sort

    Step Sort is the simplest one in these steps.

    What is sorting for Java? If you find out the answer, the principle of iSortBox is so easy to understand.

    In Java, sort is the Comparator !

    No matter how complicated the sorting rules are, just to define your own Comparators. As I mentioned above, iSortBox is not the expert at algorithm and effectiveness of sort, to be honest, those more efficient algorithms are beyond my abilities.

    So, defining your comparators under different cases or demands is the key step.


    Sorter<T> class takes charge in sorting a list. Actually, a SortConfig<T> is attached with some AbstractComparators, as for the further call, iSortBox just call Collections.sort(..) to sort a list.

    1.7

    SampleSortConfig<Student> sortConfig =newSortConfig<Student>().newBuilder() .set(4, "id", newNumberOrderComparator<>(true)) .set(1, "name", newNameComparator<>()) .combine(CombineMode.SINGLE) .useDefaultComparator(false) .build(); SortedResult<Student> result =newSortExecutor<Student>() .input(studentList) .preProcess(null) .sortConfig(sortConfig) .sort(); // must && call in order