2014-12-28 14 views
29

,Java 8, Akışları herkes dışarı denedi jdk 8. akışları kullanarak ben eg demek tamsayı listesinde yinelenen unsurları dışarı listelemek çalışıyorum yinelenen unsurları

List<Integer> numbers = Arrays.asList(new Integer[]{1,2,1,3,4,4});  

bulmak için. Yinelenenleri kaldırmak için ayrı() api'yi kullanabiliriz. Ama çoğaltılan öğeleri bulmaktan ne haber? Bana kimse yardım edebilir mi?

+2

olası yinelenen ve filtreleme işlemleri] (http://stackoverflow.com/questions/30515792/collect-stream-with-grouping-counting-and-filtering-operations) –

cevap

4

Böyle çoğaltılamaz alabilirsiniz:

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 4, 4); 
Set<Integer> duplicated = numbers.stream().filter(n -> numbers.stream().filter(x -> x == n).count() > 1).collect(Collectors.toSet()); 
+5

Bu bir O (n^2) işlem değil mi? – Trejkaz

+4

Kullanmaya çalıştığınız numaralar = Arrays.asList (400, 400, 500, 500); –

21

Bir dizi (aşağıda allItems) tüm dizi içeriğini tutmak gerekir, ancak bu (n) O:

Integer[] numbers = new Integer[] { 1, 2, 1, 3, 4, 4 }; 
Set<Integer> allItems = new HashSet<>(); 
Set<Integer> duplicates = Arrays.stream(numbers) 
     .filter(n -> !allItems.add(n)) //Set.add() returns false if the item was already in the set. 
     .collect(Collectors.toSet()); 
System.out.println(duplicates); // [1, 4] 
+0

Bence bu en verimli çözüm. – RobAu

+5

'filter()' vatansız bir yüklem gerektirir. "Çözüm" iniz, javadoc'ta verilen durumsal bir yüklemin örneğine benzer: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness –

+0

@MattMcHenry: Bu çözümün beklenmedik davranışlar üretme potansiyeline sahip olduğu anlamına mı geliyor, yoksa sadece kötü bir uygulama mı? – IcedDante

11

Temel örnek. İlk yarısı frekans haritası oluşturur, ikinci yarısı filtrelenmiş bir listeye indirir. Propably Dave cevap olarak olabildiğince verimli ama daha çok yönlü değil (gibi tam iki vs. algılamak istiyorsanız)

List<Integer> duplicates = IntStream.of(1, 2, 3, 2, 1, 2, 3, 4, 2, 2, 2) 
              .boxed() 
              .collect(Collectors.groupingBy(c -> c, Collectors.counting())) 
              .entrySet() 
              .stream() 
              .filter(p -> p.getValue() > 1) 
              .map(e -> e.getKey()) 
              .collect(Collectors.toList()); 
4

Bir O (n) yolu aşağıdaki gibi olacaktır:

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 4, 4); 
Set<Integer> duplicatedNumbersRemovedSet = new HashSet<>(); 
Set<Integer> duplicatedNumbersSet = numbers.stream().filter(n -> !duplicatedNumbersRemovedSet.add(n)).collect(Collectors.toSet()); 

uzay Bu yaklaşımda karmaşıklık iki katına çıkar, ancak bu alan bir atık değildir; Aslında, artık tek başına bir küme olarak tek başına çoğaltılmış ve tüm çoğaltmaları da kaldırılmış başka bir Set var.

10

Java 8 akışlarını zenginleştiren StreamEx kitaplığım, yalnızca en az belirtilen sayıda öğe görüntüleyen özel bir işlem olan distinct(atLeast) sağlar.

Dahili olarak, diğer miktarlarını istediğini desteklemek için, nesneleri sayar ve paralel dostu olan çözümü @Dave benzeyen (o parallelized akışı için ConcurrentHashMap kullanır
List<Integer> repeatingNumbers = StreamEx.of(numbers).distinct(2).toList(); 

ama sıralı için HashMap: Senin sorunun böyle çözülebilir). Büyük miktarda veri için .parallel().distinct(2)'u kullanarak bir hızlandırma alabilirsiniz.

+1

Soru, üçüncü taraf kütüphaneleri değil, Java Akışı hakkındadır. – fnt

62

Sen Collections.frequency kullanabilirsiniz:

numbers.stream().filter(i -> Collections.frequency(numbers, i) >1) 
       .collect(Collectors.toSet()).forEach(System.out::println); 
+2

@OussamaZoghlami [answer] (http://stackoverflow.com/a/27691091/4856258) ile aynı O (n^2) performans, muhtemelen daha basittir. Yine de burada bir not var. StackOverflow'a hoş geldiniz! –

+1

bir dize listesinde çalışmıyor –

0

ben böyle sorunun nasıl iyi bir çözüm olduğunu düşünüyorum - List => Something.a & Something.b tarafından gruplama ile listesi. Orada genişletilmiş tanımı şöyledir:

public class Test { 

    public static void test() { 

     class A { 
      private int a; 
      private int b; 
      private float c; 
      private float d; 

      public A(int a, int b, float c, float d) { 
       this.a = a; 
       this.b = b; 
       this.c = c; 
       this.d = d; 
      } 
     } 


     List<A> list1 = new ArrayList<A>(); 

     list1.addAll(Arrays.asList(new A(1, 2, 3, 4), 
       new A(2, 3, 4, 5), 
       new A(1, 2, 3, 4), 
       new A(2, 3, 4, 5), 
       new A(1, 2, 3, 4))); 

     Map<Integer, A> map = list1.stream() 
       .collect(HashMap::new, (m, v) -> m.put(
         Objects.hash(v.a, v.b, v.c, v.d), v), 
         HashMap::putAll); 

     list1.clear(); 
     list1.addAll(map.values()); 

     System.out.println(list1); 
    } 

} 

A sınıfı, sadece gelen verileri var list1 - sihirli Objects.hash olduğunu (...) :)

[gruplama saymaya, akışı toplamak ve
İlgili konular