forEach loop Java 8 cho bộ mục nhập Bản đồ


82

Tôi đang cố gắng chuyển đổi quy ước cũ cho mỗi vòng lặp cho đến java7 thành java8 cho mỗi vòng lặp cho tập mục nhập bản đồ nhưng tôi gặp lỗi. Đây là mã tôi đang cố chuyển đổi:

for (Map.Entry<String, String> entry : map.entrySet()) {
        System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
    }

Đây là những thay đổi tôi đã thực hiện:

map.forEach( Map.Entry<String, String> entry -> {
       System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());

   }); 

Tôi cũng đã thử làm điều này:

Map.Entry<String, String> entry;
   map.forEach(entry -> {
       System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());

   });

Nhưng vẫn gặp lỗi. Lỗi mà tôi gặp phải là: Chữ ký của biểu thức Lambda không khớp với chữ ký của phương thức giao diện chức năngaccept(String, String)

Câu trả lời:


191

Đọc javadoc : Map<K, V>.forEach()mong đợi một BiConsumer<? super K,? super V>đối số là và chữ ký của BiConsumer<T, U>phương thức trừu tượng là accept(T t, U u).

Vì vậy, bạn nên chuyển cho nó một biểu thức lambda nhận hai đầu vào làm đối số: khóa và giá trị:

map.forEach((key, value) -> {
    System.out.println("Key : " + key + " Value : " + value);
});

Mã của bạn sẽ hoạt động nếu bạn gọi forEach () trên tập mục nhập của bản đồ, không phải trên chính bản đồ:

map.entrySet().forEach(entry -> {
    System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}); 

Tuyệt quá. Bây giờ làm việc cả hai. Nhưng cái nào là cách tốt hơn? Trong trường hợp nào hiệu suất sẽ tốt hơn? @JBNizet
Siddharth Sachdeva

2
Phiên bản thứ hai buộc một Map.Entrythể hiện phải được tạo cho mỗi mục nhập; cái đầu tiên cung cấp cho bạn khóa và giá trị mà không cần khởi tạo. Do đó Map.Entrylà một người trung gian và bạn có thể tránh điều đó bằng cách sử dụng phiên bản đầu tiên.
Marko Topolnik

5
@Marko Topolnik: đối với hầu hết các Maptriển khai, các Map.Entryphiên bản đã tồn tại trước khi lặp lại và không cần phải tạo. Tuy nhiên, không phải xử lý Map.Entrytrong hành động là một chiến thắng về khả năng đọc và có một chút tiềm năng để có hiệu suất tốt hơn vì không cần gọi phương thức bổ sung để truy xuất khóa và giá trị.
Holger

2
@Holger Tôi sẽ nhấn mạnh hàm ý ngầm của bạn: đối với hầu hết, nhưng không phải tất cả , các Maptriển khai là đúng, ConcurrentHashMaplà một ví dụ phản chứng quan trọng.
Marko Topolnik

1
@Marko Topolnik: nhưng khi lặp lại toàn bộ ConcurrentHashMap, các trường hợp mục nhập tạm thời là điều cuối cùng bạn cần lo lắng. Tuy nhiên, chúng tôi đồng ý về việc thích hơn map.forEach((key, value) -> …);dù sao…
Holger

13

Có lẽ cách tốt nhất để trả lời những câu hỏi như "phiên bản nào nhanh hơn và tôi nên sử dụng phiên bản nào?" là nhìn vào mã nguồn:

map.forEach () - từ Map.java

default void forEach(BiConsumer<? super K, ? super V> action) {
    Objects.requireNonNull(action);
    for (Map.Entry<K, V> entry : entrySet()) {
        K k;
        V v;
        try {
            k = entry.getKey();
            v = entry.getValue();
        } catch(IllegalStateException ise) {
            // this usually means the entry is no longer in the map.
            throw new ConcurrentModificationException(ise);
        }
        action.accept(k, v);
    }
}

javadoc

map.entrySet (). forEach () - từ Iterable.java

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

javadoc

Điều này ngay lập tức tiết lộ rằng map.forEach () cũng đang sử dụng Map.Entry trong nội bộ. Vì vậy, tôi sẽ không mong đợi bất kỳ lợi ích hiệu suất nào khi sử dụng map.forEach () trên map.entrySet (). ForEach () . Vì vậy, trong trường hợp của bạn, câu trả lời thực sự phụ thuộc vào sở thích cá nhân của bạn :)

Để có danh sách đầy đủ các điểm khác biệt, vui lòng tham khảo các liên kết javadoc được cung cấp. Chúc bạn viết mã vui vẻ!


7

Bạn có thể sử dụng mã sau cho yêu cầu của mình

map.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));

2
Câu trả lời này giống với một phần câu trả lời được cung cấp bởi JB Nizet 2 năm trước đó và không cung cấp thêm thông tin hữu ích.
Madbreaks 21/09/18

0
HashMap<String,Integer> hm = new HashMap();

 hm.put("A",1);
 hm.put("B",2);
 hm.put("C",3);
 hm.put("D",4);

 hm.forEach((key,value)->{
     System.out.println("Key: "+key + " value: "+value);
 });

Vui lòng thêm một số giải thích cho câu trả lời của bạn. Điều này sẽ giúp người khác điều chỉnh câu trả lời của bạn cho phù hợp với nhu cầu của họ. Từ đánh giá .
Wai Ha Lee

0

API luồng

public void iterateStreamAPI(Map<String, Integer> map) {
    map.entrySet().stream().forEach(e -> System.out.println(e.getKey() + ":"e.getValue()));
}

0
String ss = "Pawan kavita kiyansh Patidar Patidar";
    StringBuilder ress = new StringBuilder();
    
    Map<Character, Integer> fre = ss.chars().boxed()
            .collect(Collectors.toMap(k->Character.valueOf((char) k.intValue()),k->1,Integer::sum));
    
      //fre.forEach((k, v) -> System.out.println((k + ":" + v)));
    
    fre.entrySet().forEach(e ->{
            //System.out.println(e.getKey() + ":" + e.getValue());
            //ress.append(String.valueOf(e.getKey())+e.getValue());
        }); 

    fre.forEach((k,v)->{
        //System.out.println("Item : " + k + " Count : " + v);
        ress.append(String.valueOf(k)+String.valueOf(v));
    });
    
    System.out.println(ress.toString());

Mặc dù đoạn mã này có thể là giải pháp, nhưng bao gồm phần giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Neo Anderson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.