1

I have a context map, which stores a list sorted in default order.

Map<String,Object> context = new HashMap<String,Object>();
context.put("list_all_content_default",getAllContentSortedDefault());

where getAllContentSortedDefault() returns a List by sorted in default order.

Now, I want to store the same list, in two different orders, lets say by creation date as well.

It is not possible for my clients to retrieve the list and then sort it.

So I have an option to populate the same context map twice with different key

context.put("list_all_content_createdate",getAllContentSortedCreateDate());

But this would mean, storing the same elements in context twice with different keys.

Is it possible in Java 8 to store references of methods in a Map, which can be invoked on call. e.g. something like

    context.put("list_all_content_createdate",{
List<Contents> all_contents =  (List<Contents>)context.get("list_all_content_default");

return Collections.sort(all_contents, new ContentComparatorByCreateDate(); 
});

This would help me save memory , and would create desired sort behaviour.

4
  • 1
    IMHO you can simply store the Java 8 defined function interfaces e.g. BiFunction, Predicate etc. In case you have multiple presentations of them why not just define your custom super interface. Commented Dec 22, 2015 at 6:27
  • @AlexSuo Your suggestions sound promising, unfortunately I am very new to this, can you help me with a dummy code? Commented Dec 22, 2015 at 6:29
  • Try Collections.sort(context.get("list_all_content_createdate"), new ContextComparatorByCreateDate());. No Stream required. Commented Dec 22, 2015 at 6:41
  • 1
    @MohitKanwar Just posted as an answer. See if that solves the problem for you. Commented Dec 22, 2015 at 7:01

5 Answers 5

4

Yes it's possible. You need to create a map then short by any properties by passing Comparator for that.

Stream<Map.Entry<K,V>> sorted = map.entrySet().stream()
                                   .sorted(Map.Entry.comparingByValue(comparator));
Sign up to request clarification or add additional context in comments.

Comments

2

Yes that's certainly possible. It sounds as though you just need a Comparator passed to your function which you can then sort by. I would suggest returning a Stream rather than a List if possible - then you can sort it yourself.

I'm assuming that your map needs to store multiple lists and the caller passes a key to specify the one they want. If you only have one list then you obviously don't need the map.

Map<String,List<Content>> contents = new HashMap<>();
contents.put("first", getMyContents());

public Stream<Content> getMySortedContent(Comparator comparator) {
    return contents.get("first").sorted(comparator);
}

If you really just have one list and you want to store the comparators in your map:

Map<String,Comparator<Content>> comparatorMap = new HashMap<>();
comparatorMap.put("byCreateDate", Comparator.comparingBy(Content::getData));
comparatorMap.put("byName", Comparator.comparingBy(Content::getName));

public Stream<Content> getSortedContent(String comparatorKey) {
    return getContentList().stream()
        .sorted(comparatorMap.get(comparatorKey));
}

Finally, if you really want to have a map to methods that retrieve a sorted list then you can certainly do that as well:

Map<String,Supplier<List<Content>>> supplierMap = new HashMap<>();
supplierMap.put("unsorted", this::unsortedList);
supplierMap.put("sorted_by_date" this::sortedByDate);

public List<Content> getContents(String supplierKey) {
    return supplierMap.get(supplierKey).get();
}

private List<Content> unsortedList() {
    return contentsList;
}

private List<Content> sortedByDate() {
    Collections.sort(contentsList, Comparator.comparingBy(Content::getDate));
    return contentsList;
}

I don't like the final approach much.

Let me know if any of that is confusing you and I'll add further explanation.

1 Comment

I guess the second approach suggested by you should work for me. Let me try that and then I will revert.
2

Java 8 defines each and every possible function as an interface in java.util.function package. So essentially what you need to do is just have a map of those function interfaces e.g.

Map<String, List<BiFunction>> myFunctionMap;

List<BiFunction> list;
list.add(new MyClassImplementingFunctionalInterface());

myFunctionMap.put('ABC', list);

To store all those variables. If you want the same function to be comparable at the same time, you can freely create a super interface extending from both Comparable and your function interfaces.

However, this only applies if you have 1 type of the functions in the map. If it's possible you have multiple types of functions, I reckon you need to write your own interfaces and define the methods.

NOTE: When you do things like

Collection<Integer> c = new ArrayList<Integer>();
c.forEach((i) -> { System.out.println(i); } );

Essentially you defined an anoymous object extending java.util.function.Consumer<Integer> interface. That's why you can just put such objects into the map.

Comments

0

Providing you one working dummy example related to your problem.

// helper map class which contains your collection.
class CustomSortMap extends HashMap<String, Object> {

    // Single collection object is being used.
    List<Student> studentList;

    public CustomSortMap(List<Student> studentList) {
        this.studentList = studentList;
    }

    @Override
    public List<Student> get(Object key) {
        Comparator<Student> sortType = (Comparator<Student>) super.get(key);
        Collections.sort(studentList, sortType);
        return studentList;
    }
}

public class Test {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<Student>();
        list.add(new Student(2, "dheeraj"));
        list.add(new Student(1, "shivam"));
        list.add(new Student(3, "sandeep"));
        list.add(new Student(5, "abhay"));
        list.add(new Student(4, "rohit"));

        // printing initial collection.
        printCollection(list);

        // Instantiating helper map class and passing your collection.
        CustomSortMap customMap = new CustomSortMap(list);

        // sorting collection on the basis of id.
        customMap.put("ID", new Comparator<Student>() {
            @Override
            public int compare(Student stu1, Student stu2) {
                return stu1.getId().compareTo(stu2.getId());
            }
        });
        printCollection((Collection<Student>) customMap.get("ID"));

        // sorting collection on the basis of name.
        customMap.put("NAME", new Comparator<Student>() {
            @Override
            public int compare(Student stu1, Student stu2) {
                return stu1.getName().compareTo(stu2.getName());
            }
        });
        printCollection((Collection<Student>) customMap.get("NAME"));

    }

    // printing collection.
    private static void printCollection(Collection<Student> collection) {
        for (Student student : collection) {
            System.out.println(student.getId() + " : " + student.getName());
        }
        System.out.println("===end===");
    }
}
//dummy class whose list will be used.
class Student {
    private Integer id;
    private String name;

    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof Student) {
            if (this.id == ((Student) obj).getId()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

you can directly execute above code. may be it can help you.

Comments

0
const what = (csv) => csv.split('\n')
    .slice(1, -1) 
    .map(line => line.split(';')) 
    .map(([index, color, shape, positionX, positionY, depth, moveVectorX, moveVectorY, status]) => ({
        color,
        moveVector: { x: parseFloat(moveVectorX), y: parseFloat(moveVectorY) },
        position: { x: parseFloat(positionX), y: parseFloat(positionY) }
    }));

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
The question is tagged "java" but the code in your questin doesn't look like Java code to me. Is it? Also, I think you should read How do I write a good answer. Note where it says: Brevity is acceptable, but fuller explanations are better. That means that you should also explain how your code solves the problem described in the posted question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.