단어 빈도수 Java 8
Java 8에서 List 단어의 빈도를 계산하는 방법은 무엇입니까?
List <String> wordsList = Lists.newArrayList("hello", "bye", "ciao", "bye", "ciao");
결과는 다음과 같다.
{ciao=2, hello=1, bye=2}
처음에는 map-and-reduce 방법을 사용하고 예상하고 싶지 때문에 솔루션을 공유하고 조금 달랐습니다.
Map<String, Long> collect =
wordsList.stream().collect(groupingBy(Function.identity(), counting()));
또는 정수 값의 경우 :
Map<String, Integer> collect =
wordsList.stream().collect(groupingBy(Function.identity(), summingInt(e -> 1)));
편집하다
값별로지도를 정렬하는 방법을 추가합니다.
LinkedHashMap<String, Long> countByWordSorted = collect.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> {
throw new IllegalStateException();
},
LinkedHashMap::new
));
( 참고 : 아래 편집 내용 참조 )
Mounas 답변 의 대안으로 다음은 단어 수를 대답로 계산하는 접근 방식입니다.
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ParallelWordCount
{
public static void main(String[] args)
{
List<String> list = Arrays.asList(
"hello", "bye", "ciao", "bye", "ciao");
Map<String, Integer> counts = list.parallelStream().
collect(Collectors.toConcurrentMap(
w -> w, w -> 1, Integer::sum));
System.out.println(counts);
}
}
편집 의견에 대한 응답으로 JMH 작은 테스트를로 실행하여 입력 입력 목록 크기와-length가 다른 임의의 단어를 사용 하여
toConcurrentMap
및groupingByConcurrent
접근 방식을 비교했습니다 . 이 테스트는toConcurrentMap
접근 방식이 더 빠르다는 것을 나타냅니다 . 이러한 접근 방식이 "내부"에서 얼마나 다른지 고려할 때 이와 같은 예측하기는 어렵습니다.상기 코멘트에 기초하여 상기 확장 된 바와 같이 , I는 모두 네 개의 조합을 포함하는 테스트를 연장
toMap
,groupingBy
직렬 및 병렬.결과는 여전히
toMap
접근 방식이 더 빠르지 만 사용 방식이 더 빠르지 만 지원됩니다 (나에게도 나에게는) 두 경우 모두 "동시"버전이 버전이 버전보다 느립니다 ... :
(method) (count) (wordLength) Mode Cnt Score Error Units
toConcurrentMap 1000 2 avgt 50 146,636 ± 0,880 us/op
toConcurrentMap 1000 5 avgt 50 272,762 ± 1,232 us/op
toConcurrentMap 1000 10 avgt 50 271,121 ± 1,125 us/op
toMap 1000 2 avgt 50 44,396 ± 0,541 us/op
toMap 1000 5 avgt 50 46,938 ± 0,872 us/op
toMap 1000 10 avgt 50 46,180 ± 0,557 us/op
groupingBy 1000 2 avgt 50 46,797 ± 1,181 us/op
groupingBy 1000 5 avgt 50 68,992 ± 1,537 us/op
groupingBy 1000 10 avgt 50 68,636 ± 1,349 us/op
groupingByConcurrent 1000 2 avgt 50 231,458 ± 0,658 us/op
groupingByConcurrent 1000 5 avgt 50 438,975 ± 1,591 us/op
groupingByConcurrent 1000 10 avgt 50 437,765 ± 1,139 us/op
toConcurrentMap 10000 2 avgt 50 712,113 ± 6,340 us/op
toConcurrentMap 10000 5 avgt 50 1809,356 ± 9,344 us/op
toConcurrentMap 10000 10 avgt 50 1813,814 ± 16,190 us/op
toMap 10000 2 avgt 50 341,004 ± 16,074 us/op
toMap 10000 5 avgt 50 535,122 ± 24,674 us/op
toMap 10000 10 avgt 50 511,186 ± 3,444 us/op
groupingBy 10000 2 avgt 50 340,984 ± 6,235 us/op
groupingBy 10000 5 avgt 50 708,553 ± 6,369 us/op
groupingBy 10000 10 avgt 50 712,858 ± 10,248 us/op
groupingByConcurrent 10000 2 avgt 50 901,842 ± 8,685 us/op
groupingByConcurrent 10000 5 avgt 50 3762,478 ± 21,408 us/op
groupingByConcurrent 10000 10 avgt 50 3795,530 ± 32,096 us/op
JMH에 대한 경험이 많지 언어. 여기서 뭔가 잘못했을 수도 있습니다. 제안 및 수정을 환영합니다.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
@State(Scope.Thread)
public class ParallelWordCount
{
@Param({"toConcurrentMap", "toMap", "groupingBy", "groupingByConcurrent"})
public String method;
@Param({"2", "5", "10"})
public int wordLength;
@Param({"1000", "10000" })
public int count;
private List<String> list;
@Setup
public void initList()
{
list = createRandomStrings(count, wordLength, new Random(0));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void testMethod(Blackhole bh)
{
if (method.equals("toMap"))
{
Map<String, Integer> counts =
list.stream().collect(
Collectors.toMap(
w -> w, w -> 1, Integer::sum));
bh.consume(counts);
}
else if (method.equals("toConcurrentMap"))
{
Map<String, Integer> counts =
list.parallelStream().collect(
Collectors.toConcurrentMap(
w -> w, w -> 1, Integer::sum));
bh.consume(counts);
}
else if (method.equals("groupingBy"))
{
Map<String, Long> counts =
list.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.<String>counting()));
bh.consume(counts);
}
else if (method.equals("groupingByConcurrent"))
{
Map<String, Long> counts =
list.parallelStream().collect(
Collectors.groupingByConcurrent(
Function.identity(), Collectors.<String> counting()));
bh.consume(counts);
}
}
private static String createRandomString(int length, Random random)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
int c = random.nextInt(26);
sb.append((char) (c + 'a'));
}
return sb.toString();
}
private static List<String> createRandomStrings(
int count, int length, Random random)
{
List<String> list = new ArrayList<String>(count);
for (int i = 0; i < count; i++)
{
list.add(createRandomString(length, random));
}
return list;
}
}
시간은 10000 개의 요소와 2 자 단어가있는 목록의 어떤 케이스에서만 유사합니다.
더 큰 목록 크기에 대해 동시 버전이 결국 버전보다 성능이 우수한지 확인하는 것이 모든 구성이 가능합니다.
제네릭을 사용하여 컬렉션에서 가장 빈번한 항목을 찾습니다.
private <V> V findMostFrequentItem(final Collection<V> items)
{
return items.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Functions.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparing(Entry::getValue))
.map(Entry::getKey)
.orElse(null);
}
항목 빈도 계산 :
private <V> Map<V, Long> findFrequencies(final Collection<V> items)
{
return items.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}
당신이 사용하는 경우 이클립스 컬렉션 , 당신은 단지를 변환 할 수 있습니다 List
A를 Bag
.
Bag<String> words = Lists.mutable.with("hello", "bye", "ciao", "bye", "ciao").toBag();
Assert.assertEquals(2, words.occurrencesOf("ciao"));
Assert.assertEquals(1, words.occurrencesOf("hello"));
Assert.assertEquals(2, words.occurrencesOf("bye"));
이 코드는 Java 5-8에서 작동합니다.
참고 : 저는 Eclipse 컬렉션의 커미터입니다.
지도 함수를 사용하여 빈도지도를 만드는 방법은 다음과 같습니다.
List<String> words = Stream.of("hello", "bye", "ciao", "bye", "ciao").collect(toList());
Map<String, Integer> frequencyMap = new HashMap<>();
words.forEach(word ->
frequencyMap.merge(word, 1, (v, newV) -> v + newV)
);
System.out.println(frequencyMap); // {ciao=2, hello=1, bye=2}
또는
words.forEach(word ->
frequencyMap.compute(word, (k, v) -> v != null ? v + 1 : 1)
);
여기에 내가 만든 해결책을 제시 할 것입니다 (그룹화가있는 것이 훨씬 낫습니다 :)).
static private void test0(List<String> input) {
Set<String> set = input.stream()
.collect(Collectors.toSet());
set.stream()
.collect(Collectors.toMap(Function.identity(),
str -> Collections.frequency(input, str)));
}
내 0.02 $
배열이 주어지면 또 다른 2 센트 :
import static java.util.stream.Collectors.*;
String[] str = {"hello", "bye", "ciao", "bye", "ciao"};
Map<String, Integer> collected
= Arrays.stream(str)
.collect(groupingBy(Function.identity(),
collectingAndThen(counting(), Long::intValue)));
public class Main {
public static void main(String[] args) {
String testString ="qqwweerrttyyaaaaaasdfasafsdfadsfadsewfywqtedywqtdfewyfdweytfdywfdyrewfdyewrefdyewdyfwhxvsahxvfwytfx";
long java8Case2 = testString.codePoints().filter(ch -> ch =='a').count();
System.out.println(java8Case2);
ArrayList<Character> list = new ArrayList<Character>();
for (char c : testString.toCharArray()) {
list.add(c);
}
Map<Object, Integer> counts = list.parallelStream().
collect(Collectors.toConcurrentMap(
w -> w, w -> 1, Integer::sum));
System.out.println(counts);
}
}
참조 URL : https://stackoverflow.com/questions/29122394/word-frequency-count-java-8
'ProgramingTip' 카테고리의 다른 글
Python DataFrame 부분 설정 (0) | 2021.01.10 |
---|---|
오류 : lombok 1.16.2로 업그레이드 한 후 패키지 javax.annotation이 존재하지 않습니다. (0) | 2021.01.10 |
ES6 자바 펼쳐에서 기호 (@)는 무엇을 소유하고 있습니까? (0) | 2021.01.10 |
Angular 2 FormGroup에서 모든 유효성 검사 오류 가져 오기 (0) | 2021.01.10 |
Google 스프레드 시트에 Lakhs 및 Crores 표시 (0) | 2021.01.09 |