2017-07-05 18 views
6

TreeMap numaralı telefon numaralarının frekanslarını, ArrayList numaralı telefondan o frekansa sahip olan anahtarlar ve sayılar gibi sıklıklarla girmek istiyorum.Inverted Collectors.toMap bir ArrayList öğesine eklemek için

Ben iki sorun:

Ben bir "statik olmayan yöntemler statik bağlam başvurulan edilemez" alıyorum ilk parametre hatası (AFAIK akışı bir nesneye başvurur

1) - neler oluyor? 0)

2) Collectors.toMap() için 4 parametre vardır - parametre 4'ün yeni bir TreeMap> ile başlatılmasını gerektirdiği gibi, parametre 2 bir ArrayList add() işlevi olabilir ve parametre 3 boş olabilir (belki) . Bu nasıl yapılır? Olmam gereken yere kadar https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html almak nasıl kullanamazsınız Şu anda

import java.util.*; 
import java.util.function.Function; 
import java.util.stream.Collectors; 

public class Main { 

    public static void main(String[] args) { 

     List<Integer> array = Arrays.asList(1, 2, 4, 5, 6, 4, 8, 4, 2, 3); 

     Map<Integer, Long> m = array.stream() 
      .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); 

     System.out.println(m); 

     TreeMap<Long, List<Integer>> tm = m.entrySet().stream() 
      .collect(Collectors.toMap(Map.Entry::getValue, ...)); 

.

cevap

6

Niçin akıl yürütmenizde haklısınız ... Sadece 3-rd argümanı, değerlerinizi aynı anahtar için birleştirdiğiniz yerdir - bu yüzden atlayamazsınız. (Sen çıkış Map değerleri ArrayList s olduğundan emin olmak için Collectors.toCollection(ArrayList::new) ile Collectors.toList() yerini alabilir

Map<Long, List<Integer>> tm = 
    m.entrySet() 
    .stream() 
    .collect(Collectors.groupingBy(Map.Entry::getValue, // group the entries by the 
                 // value (the frequency) 
            TreeMap::new, // generate a TreeMap 
            Collectors.mapping (Map.Entry::getKey, 
                 Collectors.toList()))); // the 
                 // value of the output TreeMap 
                 // should be a List of the 
                 // original keys 

: Ben Collectors.groupingBy düşünüyorum

TreeMap<Long, List<Integer>> tm = m.entrySet().stream() 
      .collect(Collectors.toMap(
        Entry::getValue, 
        x -> { 
         List<Integer> list = new ArrayList<>(); 
         list.add(x.getKey()); 
         return list; 
        }, 
        (left, right) -> { 
        left.addAll(right); 
        return left; 
        }, 
        TreeMap::new)); 
+0

Array.asList satırı, eldeki sorudan dikkati dağıtır. –

+0

@JohnEstess mükemmel, ben de kaldırmak için cevabı düzenledim de – Eugene

+0

Aşağıdaki 'toMap' ikinci argüman olarak alarak birkaç satır kaydedebilirsiniz: 'x -> yeni ArrayList <> (singletonList (x.getKey ())) '. – Lii

6

Aradığınız şeyi elde etmek Collectors.toMap daha mantıklı Geçerli uygulama toList() zaten java.util.ArrayList örneğiyle sonuçlanır). senin örnek girişi için

, bu şu TreeMap üretir: Ben ters bir harita oluşturmak için akışlarını kullanmak ister

{1=[1, 3, 5, 6, 8], 2=[2], 3=[4]} 
7

. Bunun yerine, tıpkı olacaktır: ters harita oluşturmak kod kısa olduğu için

Map<Long, List<Integer>> tm = new TreeMap<>(); 
m.forEach((num, freq) -> tm.computeIfAbsent(freq, k -> new ArrayList<>()).add(num)); 

System.out.println(tm); // {1=[1, 3, 5, 6, 8], 2=[2], 3=[4]} 

, tek adımda frekansları ve ters haritayı oluşturmak, hem de Collectors.collectingAndThen kullanabilirsiniz: Ben düzenlenmiş

TreeMap<Long, List<Integer>> invertedFrequenciesMap = array.stream() 
    .collect(Collectors.collectingAndThen(
     Collectors.groupingBy(Function.identity(), Collectors.counting()), 
     map -> { 
      TreeMap<Long, List<Integer>> tm = new TreeMap<>(); 
      map.forEach((num, freq) -> 
        tm.computeIfAbsent(freq, k -> new ArrayList<>()).add(num)); 
      return tm; 
     })); 
+2

kesinlikle +1 (aynı şeyi başlangıçta göstermek istedim, ama OP, toMap ile nasıl yapılacağını sordu ...) – Eugene

+1

Yukarıdaki cevapların hepsinin üstünde oy kullanıyorum, yani sizde benim de var. :) –

İlgili konular