Tôi muốn áp dụng một chức năng cho một bộ sưu tập Java, trong trường hợp cụ thể này là một bản đồ. Có cách nào tốt đẹp để làm điều này? Tôi có một bản đồ và chỉ muốn chạy trim() trên tất cả các giá trị trong bản đồ và có bản đồ phản ánh các bản cập nhật.Phương pháp thu thập/áp dụng bản đồ Java tương đương?
Trả lời
Với lambdas Java 8, đây là một liner:
map.replaceAll((k, v) -> v.trim());
Vì lợi ích của lịch sử, đây là một phiên bản mà không lambdas:
public void trimValues(Map<?, String> map) {
for (Map.Entry<?, String> e : map.entrySet()) {
String val = e.getValue();
if (val != null)
e.setValue(val.trim());
}
}
Hoặc, tổng quát hơn:
interface Function<T> {
T operate(T val);
}
public static <T> void replaceValues(Map<?, T> map, Function<T> f)
{
for (Map.Entry<?, T> e : map.entrySet())
e.setValue(f.operate(e.getValue()));
}
Util.replaceValues(myMap, new Function<String>() {
public String operate(String val)
{
return (val == null) ? null : val.trim();
}
});
Cho dù bạn có thể sửa đổi bộ sưu tập của mình tại chỗ hay không phụ thuộc vào loại đối tượng trong bộ sưu tập.
Nếu các đối tượng đó không thay đổi (chuỗi là) thì bạn không thể lấy các mục từ bộ sưu tập và sửa đổi chúng - thay vào đó bạn sẽ cần lặp lại bộ sưu tập, gọi hàm có liên quan và sau đó đặt kết quả giá trị trở lại.
Bạn sẽ phải lặp qua tất cả các mục nhập và cắt từng giá trị Chuỗi. Vì String là bất biến, bạn sẽ phải đặt lại nó trong bản đồ. Một cách tiếp cận tốt hơn có thể là cắt các giá trị khi chúng được đặt trong bản đồ.
Có thể quá mức cần thiết cho một cái gì đó như thế này, nhưng có một số tiện ích thực sự tốt cho các loại sự cố này trong thư viện Apache Commons Collections.
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "a ");
map.put("key2", " b ");
map.put("key3", " c");
TransformedMap.decorateTransform(map,
TransformerUtils.nopTransformer(),
TransformerUtils.invokerTransformer("trim"));
Tôi rất khuyên bạn nên Jakarta Commons Cookbook từ O'Reilly.
Chỉ muốn đề cập đến phiên bản bất biến trong thư viện Bộ sưu tập Apache Commons: Bộ sưu tậpUtils.collect (Bộ sưu tập inputCollection, Biến áp biến áp) – Jakub
Bạn cũng có thể có một cái nhìn tại Google Collections
Loại mơ hồ ... ít nhất là cung cấp liên kết và mô tả/ví dụ về cách sử dụng Google Bộ sưu tập giải quyết vấn đề? –
Tôi không biết một cách để làm điều đó với JDK thư viện khác hơn câu trả lời chấp nhận của bạn, tuy nhiên Google Bộ sưu tập cho phép bạn làm những điều sau đây, với các lớp học com.google.collect.Maps
và com.google.common.base.Function
:
Map<?,String> trimmedMap = Maps.transformValues(untrimmedMap, new Function<String, String>() {
public String apply(String from) {
if (from != null)
return from.trim();
return null;
}
}
sự khác biệt lớn nhất của phương pháp đó với một đề xuất là nó cung cấp một cái nhìn vào bản đồ ban đầu của bạn, có nghĩa là, trong khi nó luôn luôn là đồng bộ với bản đồ ban đầu của bạn, phương pháp apply
có thể được gọi nhiều lần nếu bạn đang thao tác sai d bản đồ nặng nề.
Phương thức tương tự Collections2.transform(Collection<F>,Function<F,T>)
có sẵn cho các bộ sưu tập.
tôi đã đưa ra một lớp "Mapper"
public static abstract class Mapper<FromClass, ToClass> {
private Collection<FromClass> source;
// Mapping methods
public abstract ToClass map(FromClass source);
// Constructors
public Mapper(Collection<FromClass> source) {
this.source = source;
}
public Mapper(FromClass ... source) {
this.source = Arrays.asList(source);
}
// Apply map on every item
public Collection<ToClass> apply() {
ArrayList<ToClass> result = new ArrayList<ToClass>();
for (FromClass item : this.source) {
result.add(this.map(item));
}
return result;
}
}
đó tôi sử dụng như thế:
Collection<Loader> loaders = new Mapper<File, Loader>(files) {
@Override public Loader map(File source) {
return new Loader(source);
}
}.apply();
tôi đã kết thúc bằng một đột biến của câu trả lời @ Erickson của, đột biến:
- trả lại
Collection
mới, không sửa đổi tại chỗ - trở
Collection
s với các yếu tố của loại tương ứng với kiểu trả về của các bản đồ hỗ trợFunction
- qua một trong hai giá trị của một bản đồ hoặc các yếu tố của một danh sách
Code:
public static interface Function<L, R> {
L operate(R val);
}
public static <K, L, R> Map<K, L> map(Map<K, R> map, Function<L, R> f) {
Map<K, L> retMap = new HashMap<K, L>();
for (Map.Entry<K, R> e : map.entrySet()) retMap.put(e.getKey(), f.operate(e.getValue()));
return retMap;
}
public static <L, R> List<L> map(List<R> list, Function<L, R> f) {
List<L> retList = new ArrayList<L>();
for (R e : list) retList.add(f.operate(e));
return retList;
}
+1 cho hàm lambda mẫu – Alnitak
Hey erickson - nơi tôi có thể tìm hiểu về cú pháp này: Bản đồ , String> map ?? Tôi chỉ học java và đã không đi qua bất cứ điều gì như thế .. bất kỳ hướng nào sẽ được đánh giá cao! –
@jamesemanon Điều đó có nghĩa là bản đồ bạn chuyển sang phương thức này có thể có bất kỳ loại khóa nào, nhưng giá trị phải là một 'Chuỗi'. Bạn có thể tìm hiểu thông tin cơ bản từ [Hướng dẫn Java] (https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html). [Câu hỏi thường gặp chung của Angelika Langer] (http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html) có nhiều thông tin chi tiết hơn về tất cả các khía cạnh của Java Generics. – erickson