Tôi cần một chức năng bản đồ . Có cái gì đó như thế này trong Java chưa?
(Dành cho những ai thắc mắc: Tất nhiên tôi biết cách tự mình thực hiện chức năng tầm thường này ...)
Tôi cần một chức năng bản đồ . Có cái gì đó như thế này trong Java chưa?
(Dành cho những ai thắc mắc: Tất nhiên tôi biết cách tự mình thực hiện chức năng tầm thường này ...)
Câu trả lời:
Không có khái niệm về một hàm trong JDK như java 6.
Quả ổi có giao diện Chức năng và
phương thức cung cấp chức năng bạn yêu cầu.
Collections2.transform(Collection<E>, Function<E,E2>)
Thí dụ:
// example, converts a collection of integers to their
// hexadecimal string representations
final Collection<Integer> input = Arrays.asList(10, 20, 30, 40, 50);
final Collection<String> output =
Collections2.transform(input, new Function<Integer, String>(){
@Override
public String apply(final Integer input){
return Integer.toHexString(input.intValue());
}
});
System.out.println(output);
Đầu ra:
[a, 14, 1e, 28, 32]
Ngày nay, với Java 8, thực sự có một hàm bản đồ, vì vậy tôi có thể viết mã theo cách ngắn gọn hơn:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Kể từ Java 8, có một số tùy chọn tiêu chuẩn để thực hiện điều này trong JDK:
Collection<E> in = ...
Object[] mapped = in.stream().map(e -> doMap(e)).toArray();
// or
List<E> mapped = in.stream().map(e -> doMap(e)).collect(Collectors.toList());
Xem java.util.Collection.stream()
và java.util.stream.Collectors.toList()
.
toList()
. Thay thế bằng loại khác:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
được thay thế bằng chỉ doMap
?
foo::doMap
hoặc Foo::doMap
.
Có một thư viện tuyệt vời tên là Java chức năng xử lý nhiều thứ bạn muốn Java có nhưng nó không có. Một lần nữa, Scala cũng có ngôn ngữ tuyệt vời này thực hiện mọi thứ Java nên làm nhưng không tương thích với mọi thứ được viết cho JVM.
a.map({int i => i + 42});
họ có mở rộng trình biên dịch không? hoặc thêm tiền xử lý?
Hãy cẩn thận với Collections2.transform()
ổi. Ưu điểm lớn nhất của phương pháp đó cũng là mối nguy hiểm lớn nhất của nó: sự lười biếng.
Nhìn vào tài liệu Lists.transform()
mà tôi tin rằng cũng áp dụng cho Collections2.transform()
:
Các chức năng được áp dụng một cách lười biếng, được gọi khi cần thiết. Điều này là cần thiết để danh sách được trả về là một khung nhìn, nhưng điều đó có nghĩa là hàm này sẽ được áp dụng nhiều lần cho các hoạt động hàng loạt như List.contains (java.lang.Object) và List.hashCode (). Để điều này thực hiện tốt, chức năng nên được nhanh chóng. Để tránh đánh giá lười biếng khi danh sách trả về không cần phải là chế độ xem, hãy sao chép danh sách được trả về vào danh sách mới bạn chọn.
Ngoài ra trong tài liệu của Collections2.transform()
họ đề cập đến việc bạn có được chế độ xem trực tiếp, sự thay đổi đó trong danh sách nguồn ảnh hưởng đến danh sách được chuyển đổi. Loại hành vi này có thể dẫn đến các vấn đề khó theo dõi nếu nhà phát triển không nhận ra cách thức hoạt động.
Nếu bạn muốn có một "bản đồ" cổ điển hơn, nó sẽ chỉ chạy một lần và một lần duy nhất, thì bạn FluentIterable
cũng nên sử dụng Guava, một hoạt động đơn giản hơn nhiều. Dưới đây là ví dụ google cho nó:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
đây là phương pháp bản đồ. Nó sử dụng cùng chức năng <> "gọi lại" như Collections.transform()
. Danh sách bạn nhận được là chỉ đọc, sử dụng copyInto()
để có được danh sách đọc-ghi.
Nếu không thì tất nhiên khi java8 ra mắt với lambdas, điều này sẽ lỗi thời.
Đây là một lib chức năng khác mà bạn có thể sử dụng bản đồ: http://code.google.com.vn/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Mặc dù đó là một câu hỏi cũ tôi muốn đưa ra một giải pháp khác:
Chỉ cần xác định hoạt động của riêng bạn bằng cách sử dụng java generic và java 8 stream:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Hơn bạn có thể viết mã như thế này:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);