Tôi quyết định viết một số hàm bậc cao phổ biến trong Java (bản đồ, bộ lọc, giảm, v.v.) được an toàn thông qua Generics, và tôi đang gặp vấn đề với ký tự đại diện khớp một chức năng cụ thể.Generics Java - triển khai các hàm bậc cao hơn như bản đồ
Chỉ cần được hoàn tất, giao diện functor là thế này:
/**
* The interface containing the method used to map a sequence into another.
* @param <S> The type of the elements in the source sequence.
* @param <R> The type of the elements in the destination sequence.
*/
public interface Transformation<S, R> {
/**
* The method that will be used in map.
* @param sourceObject An element from the source sequence.
* @return The element in the destination sequence.
*/
public R apply(S sourceObject);
}
Chức năng gây phiền hà cũng giống như một bản đồ , nhưng thay vì chuyển một Collection nó biến đổi một Bản đồ (tại I đầu tiên nghĩ rằng nó nên được gọi là mapMap
, nhưng nó có vẻ ngu ngốc đến mức tôi đã gọi nó là remapEntries
).
phiên bản đầu tiên của tôi là (và tham gia một ngồi, bởi vì chữ ký là khá một con quái vật):
/**
* <p>
* Fills a map with the results of applying a mapping function to
* a source map.
* </p>
* Considerations:
* <ul>
* <li>The result map must be non-null, and it's the same object what is returned
* (to allow passing an unnamed new Map as argument).</li>
* <li>If the result map already contained some elements, those won't
* be cleared first.</li>
* <li>If various elements have the same key, only the last entry given the
* source iteration order will be present in the resulting map (it will
* overwrite the previous ones).</li>
* </ul>
*
* @param <SK> Type of the source keys.
* @param <SV> Type of the source values.
* @param <RK> Type of the result keys.
* @param <RV> Type of the result values.
* @param <MapRes>
* @param f The object that will be used to remapEntries.
* @param source The map with the source entries.
* @param result The map where the resulting entries will be put.
* @return the result map, containing the transformed entries.
*/
public static <SK, SV, RK, RV, MapRes extends Map<RK, RV>> MapRes remapEntries(final Transformation<Map.Entry<SK, SV>, Map.Entry<RK,RV>> f, final Map<SK, SV> source, MapRes result) {
for (Map.Entry<SK, SV> entry : source.entrySet()) {
Map.Entry<RK, RV> res = f.apply(entry);
result.put(res.getKey(), res.getValue());
}
return result;
}
Và nó có vẻ là khá đúng, nhưng vấn đề là việc chuyển đổi sử dụng phải phù hợp chính xác nhập các thông số, khiến việc sử dụng lại các chức năng bản đồ cho các loại tương thích trở nên khó khăn. Vì vậy, tôi quyết định thêm ký tự đại diện cho chữ ký, và nó đã kết thúc như thế này:
public static <SK, SV, RK, RV, MapRes extends Map<RK, RV>> MapRes remapEntries(final Transformation<? super Map.Entry<? super SK, ? super SV>, ? extends Map.Entry<? extends RK, ? extends RV>> f, final Map<SK, SV> source, MapRes result) {
for (Map.Entry<SK, SV> entry : source.entrySet()) {
Map.Entry<? extends RK, ? extends RV> res = f.apply(entry);
result.put(res.getKey(), res.getValue());
}
return result;
}
Nhưng khi tôi đang cố gắng để kiểm tra nó, phù hợp với ký tự đại diện thất bại:
@Test
public void testRemapEntries() {
Map<String, Integer> things = new HashMap<String, Integer>();
things.put("1", 1);
things.put("2", 2);
things.put("3", 3);
Transformation<Map.Entry<String, Number>, Map.Entry<Integer, String>> swap = new Transformation<Entry<String, Number>, Entry<Integer, String>>() {
public Entry<Integer, String> apply(Entry<String, Number> sourceObject) {
return new Pair<Integer, String>(sourceObject.getValue().intValue(), sourceObject.getKey()); //this is just a default implementation of a Map.Entry
}
};
Map<Integer, String> expected = new HashMap<Integer, String>();
expected.put(1, "1");
expected.put(2, "2");
expected.put(3, "3");
Map<Integer, String> result = IterUtil.remapEntries(swap, things, new HashMap<Integer, String>());
assertEquals(expected, result);
}
Lỗi này là:
method remapEntries in class IterUtil cannot be applied to given types
required: Transformation<? super java.util.Map.Entry<? super SK,? super SV>,? extends java.util.Map.Entry<? extends RK,? extends RV>>,java.util.Map<SK,SV>,MapRes
found: Transformation<java.util.Map.Entry<java.lang.String,java.lang.Number>,java.util.Map.Entry<java.lang.Integer,java.lang.String>>,java.util.Map<java.lang.String,java.lang.Integer>,java.util.HashMap<java.lang.Integer,java.lang.String>
Vì vậy, bất kỳ gợi ý nào về cách sửa lỗi này? Hoặc tôi có nên từ bỏ và viết các vòng lặp rõ ràng cho việc này không?^_^
Hãy xem https://github.com/GlenKPeterson/fp4java7 Các hàm bậc cao hơn của Java được thực hiện dưới dạng các transormations lười trên các bộ sưu tập không thể thay đổi (hoặc có thể thay đổi). Một số biến đổi lười biếng liên tục cũng được thực hiện. Đó là một giao diện hoàn toàn chung chung, mặc dù một vài phôi thích hợp trong việc thực hiện. – GlenPeterson
hehe, bạn trễ 3 năm @GlenPeterson;) btw, thêm một số bài kiểm tra! : D – fortran