Java 函数式编程:创建函数映射

问题描述 投票:0回答:5

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

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

其中 getAllContentSortedDefault() 返回按默认顺序排序的列表。

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

我的客户不可能检索列表然后对其进行排序。

所以我可以选择使用不同的键两次填充相同的上下文映射

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

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

java functional-programming java-8
5个回答
4
投票

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

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

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
投票

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>
接口的匿名对象。这就是为什么你可以将这些对象放入地图中。


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

}

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


0
投票

const parseCSV = (csv) => csv.split(' ') .slice(1, -1) .map(line => line.split(';')) .map(([索引、颜色、形状、positionX、positionY、深度、moveVectorX、moveVectorY、状态]) => ({ 颜色, moveVector: { x: parseFloat(moveVectorX), y: parseFloat(moveVectorY) }, 位置: { x: parseFloat(positionX), y: parseFloat(positionY) } }));

© www.soinside.com 2019 - 2024. All rights reserved.