2017-05-13 30 views
8

Şöyle bir sınıf IndexEntry vardır:Bir Harita'da en sık kullanılan sözcüğü nasıl bulabilirim ve Java 8 akışlarını kullanarak buna karşılık gelen sıklıkta karşılaşıyorum?

public class IndexEntry implements Comparable<IndexEntry> 
{ 
    private String word; 
    private int frequency; 
    private int documentId; 
    ... 
    //Simple getters for all properties 
    public int getFrequency() 
    { 
     return frequency; 
    } 
    ... 
} 

Sanırım biraz IndexEntry s bir String kelime eşleme am (Anahtar başına birden çok değer için sağlar) bir Guava SortedSetMultimap bu sınıfın nesneleri depolamak am . Sahne arkasında, her bir kelimeyi SortedSet<IndexEntry> ile eşler.

Belgedeki belgelere ve bunların oluşum sıklıklarına bir dizi endeksli yapı oluşturmaya çalışıyorum.

En sık kullanılan kelimenin sayımını nasıl elde edeceğimi biliyorum, ancak sözcüğü kendim göremiyorum. onlar gerçekten kullanışlı görünüyor çünkü Java 8 özelliklerini öğrenmeye çalışıyorum

public int mostFrequentWordFrequency() 
{ 
    return entries 
      .keySet() 
      .stream() 
      .map(this::totalFrequencyOfWord) 
      .max(Comparator.naturalOrder()).orElse(0); 
} 

public int totalFrequencyOfWord(String word) 
{ 
    return getEntriesOfWord(word) 
      .stream() 
      .mapToInt(IndexEntry::getFrequency) 
      .sum(); 
} 

public SortedSet<IndexEntry> getEntriesOfWord(String word) 
{ 
    return entries.get(word); 
} 

: Burada

ben yardımcı yöntemleri ile birlikte, entries SortedSetMultimap en yaygın terim, sayısını almak zorunda budur . Ancak, akışımı istediğim gibi çalıştıramayacağım. Akıntının sonunda hem kelimeyi hem de frekansı elde edebilmeyi isterim, fakat eğer bu kelimeye sahip olursam, o kelimenin tam anlamını kolayca elde edebilirim.

Şu anda, hiçbir şey yapamayacağım bir Stream<SortedSet<IndexEntry>> ile bitmeye devam ediyorum. Sıklık olmadan en sık kullanılan kelimeyi nasıl elde edeceğimi bilmiyorum, ancak frekansım varsa karşılık gelen kelimeyi takip edemiyorum. Her ikisini de kaydetmek için WordFrequencyPair POJO sınıfı oluşturmayı denedim, ancak daha sonra sadece Stream<SortedSet<WordFrequencyPair>> kullanıyorum ve bunun nasıl yararlı bir şeyle eşleştirileceğini anlayamadım.

Neyi eksik?

import com.google.common.collect.*; 

public class Main { 

    TreeMultimap<Integer, IndexEntry> entries = TreeMultimap.<Integer, IndexEntry>create(Ordering.arbitrary(), Ordering.natural().reverse()); 

    public static void main(String[] args) { 
     // Add elements to `entries` 

     // Get the most frequent word in document #1 
     String mostFrequentWord = entries.get(1).first().getWord(); 
    } 

} 

class IndexEntry implements Comparable<IndexEntry> { 

    private String word; 

    private int frequency; 

    private int documentId; 

    public String getWord() { 
     return word; 
    } 

    public int getFrequency() { 
     return frequency; 
    } 

    public int getDocumentId() { 
     return documentId; 
    } 

    @Override 
    public int compareTo(IndexEntry i) { 
     return Integer.compare(frequency, i.frequency); 
    } 

} 

Böylece takip ile önce sahip yöntemleri uygulayabilirsiniz:

cevap

6

Ben oldukça word daha TreeMultimap ait anahtar olarak documentId kullanmak için daha iyi bir tasarım olacağını düşünüyorum

JDK tarafından
public static int totalFrequencyOfWord(String word) { 
    return entries.values() 
        .stream() 
        .filter(i -> word.equals(i.getWord())) 
        .mapToInt(IndexEntry::getFrequency) 
        .sum(); 
} 

/** 
* This method iterates through the values of the {@link TreeMultimap}, 
* searching for {@link IndexEntry} objects which have their {@code word} 
* field equal to the parameter, word. 
* 
* @param word 
*  The word to search for in every document. 
* @return 
*  A {@link List<Pair<Integer, Integer>>} where each {@link Pair<>} 
*  will hold the document's ID as its first element and the frequency 
*  of the word in the document as its second element. 
* 
* Note that the {@link Pair} object is defined in javafx.util.Pair 
*/ 
public static List<Pair<Integer, Integer>> totalWordUses(String word) { 
    return entries.values() 
        .stream() 
        .filter(i -> word.equals(i.getWord())) 
        .map(i -> new Pair<>(i.getDocumentId(), i.getFrequency())) 
        .collect(Collectors.toList()); 
} 
+0

, ben belirli bir sözcüğe bu belgede ortaya çıkma sayısı ile birlikte mevcuttu belge kimlikleri tamamını görmek gerektiğini varsayalım. Örneğinizde, bunu nasıl yapacağım? –

+0

Bunu yapmak için bir yöntem yazacağım ve nasıl çalıştığını açıklayacağım –

+0

Bunun işe yarayacağını düşünüyorum. Teşekkürler! –

0

Yerli çözüm:

entries.keySet().stream() 
    .collect(groupingBy(IndexEntry::getWord, summingInt(IndexEntry::getFrequency))) 
    .values().stream().max(Comparator.naturalOrder()).orElse(0L); 

Ya Yani StreamEx

StreamEx.of(entries.keySet()) 
    .groupingBy(IndexEntry::getWord, summingInt(IndexEntry::getFrequency)) 
    .values().stream().max(Comparator.naturalOrder()).orElse(0L);