Java Functional Programming:创建函数映射

时间:2015-12-22 06:21:45

标签: java functional-programming java-8

我有一个上下文映射,它存储按默认顺序排序的列表。

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

其中getAllContentSortedDefault()按默认顺序排序返回List。

现在,我想以两个不同的顺序存储相同的列表,也可以按创建日期来说。

我的客户无法检索列表然后对其进行排序。

所以我可以选择使用不同的键

填充相同的上下文映射两次
context.put("list_all_content_createdate",getAllContentSortedCreateDate());

但这意味着,使用不同的密钥将相同的元素存储在上下文中两次。

在Java 8中是否可以在Map中存储方法的引用,可以在调用时调用它。 例如

之类的东西
    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(); 
});

这可以帮助我节省内存,并创建所需的排序行为。

4 个答案:

答案 0 :(得分:4)

是的,这是可能的。您需要通过传递Comparator来创建一个地图然后通过任何属性缩短。

Stream<Map.Entry<K,V>> sorted = map.entrySet().stream()
                                   .sorted(Map.Entry.comparingByValue(comparator));

答案 1 :(得分:2)

是的,这当然是可能的。听起来好像你只需要传递给你的函数Comparator然后你可以排序。如果可能,我建议您返回Stream而不是List - 然后您可以自行排序。

我假设您的地图需要存储多个列表,并且调用者传递一个键来指定他们想要的那个。如果您只有一个列表,那么您显然不需要地图。

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

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

如果您真的只有一个列表,并且想要将比较器存储在地图中:

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));
}

最后,如果你真的想拥有一个检索排序列表的方法的地图,那么你当然也可以这样做:

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;
}

我不喜欢最后的方法。

如果有任何问题让我感到困惑,请告诉我,我会补充进一步的解释。

答案 2 :(得分:2)

Java 8将每个可能的函数定义为java.util.function包中的接口。所以你需要做的就是拥有这些功能接口的映射,例如

Map<String, List<BiFunction>> myFunctionMap;

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

myFunctionMap.put('ABC', list);

存储所有这些变量。如果您希望同一功能可以同时进行比较,您可以自由地创建从Comparable和您的功能接口扩展的超级接口。

但是,这仅适用于地图中有1种类型的函数。如果你有可能有多种类型的函数,我想你需要编写自己的接口并定义方法。

注意:当您执行

之类的操作时
Collection<Integer> c = new ArrayList<Integer>();
c.forEach((i) -> { System.out.println(i); } );

基本上你定义了一个扩展java.util.function.Consumer<Integer>接口的anoymous对象。这就是为什么你可以将这些对象放入地图中。

答案 3 :(得分:0)

为您提供一个与您的问题相关的工作虚拟示例。

// 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;
    }

}

你可以直接执行上面的代码。也许它可以帮到你。