2015-07-24 27 views
11

Tôi có một luồng Java 8 mà từ đó tôi muốn (thống nhất) ngẫu nhiên chọn một phần tử hay không. Luồng có thể chứa từ 0 đến hàng chục nghìn phần tử.Tôi có thể kiểm tra xem luồng Java 8 có chứa ít nhất n phần tử

Tôi đã triển khai thuật toán chọn một mẫu bằng cách sử dụng mẫu giống MapReduce, nhưng đối với các luồng rất nhỏ, có thể sẽ chỉ hiệu quả hơn khi thu thập các mục vào Danh sách và trả về một chỉ mục ngẫu nhiên. Cho rằng tôi phải đếm chúng, tuy nhiên. Các luồng có phương thức count() nhưng đếm được tất cả, tôi không thực sự quan tâm đến số lượng thực, tất cả những gì tôi quan tâm là liệu nó có chứa nhiều hơn số được xác định hay không. Có ai biết nếu một phương pháp như vậy tồn tại? Tôi không thể tìm thấy nó nhưng có thể có một cái gì đó tôi nhìn hoặc lừa một số thông minh cho việc tìm kiếm nó anyway.

P .: Tôi biết rằng đôi khi không cần tối ưu hóa mã; nhưng tôi vẫn muốn thử nó, chỉ vì kinh nghiệm. Tôi là học sinh.

PPS: Tôi đã sao chép thuật toán của tôi ở đây, trong trường hợp có ai quan tâm (hoặc muốn tìm kiếm lỗi, tôi đã không kiểm tra nó chưa ;-)

stream 
    .parallel() 
    .map(t -> new Pair<T, Integer>(t, 1)) 
    .reduce((Pair<T, Integer> t, Pair<T, Integer> u) -> { 
     if (rand.nextDouble() <= (t.getValue1()/(double) (t.getValue1() + u.getValue1()))) { 
      return new Pair<>(t.getValue0(), t.getValue1() + u.getValue1()); 
     } else { 
      return new Pair<>(u.getValue0(), t.getValue1() + u.getValue1()); 
     } 
    }) 
    .map(t -> t.getValue0()); 

(Các cặp từ org. javatuples, bây giờ Java hỗ trợ các giao diện giống như lập trình hàm, việc thiếu các bộ dữ liệu trở nên hơi đau đớn).

+0

Cho rằng luồng có thể là luồng chỉ đọc một lần và luồng không biết liệu phần tử khác có khả dụng hay không cho đến khi được đọc, tôi không t xem cách tính như vậy có thể hoạt động trong mọi trường hợp. Cá nhân tôi sẽ không viết thuật toán của bạn thông qua một bước loại bản đồ/giảm - Tôi chỉ cần sử dụng mã như thế này: http://stackoverflow.com/questions/966108/choose-random-array-element-satisfying-certain-property/966118 # 966118 với một trình lặp. –

+0

Cảm ơn bạn đã trả lời. Tôi đã có điều đó, nhưng tôi không thấy nó có thể chuyển đổi một luồng thành một trình lặp. Cảm ơn con trỏ. –

+0

"Đối với các luồng rất nhỏ, có lẽ sẽ hiệu quả hơn khi chỉ thu thập các mục vào Danh sách". Tại sao? –

Trả lời

0

Tôi khuyên bạn nên thử lấy thông tin này từ nguồn dữ liệu cho luồng. Bạn lấy dữ liệu cho luồng từ đâu? Nếu nguồn (ví dụ một số bộ sưu tập) có thể cung cấp cho bạn số phần tử bạn đã đặt. Nếu đó là một số chức năng của nhà sản xuất, hãy kiểm tra xem nó hoạt động như thế nào và liệu có thể ước tính kích thước trả trước hay không.

Thời điểm tôi nhập "luồng" Tôi thường bắt đầu nghĩ đến "công thức" về những gì tôi muốn làm với dữ liệu này, thay vì dữ liệu thực tế. Tôi nghĩ rằng đó là gần với cách dòng được thiết kế (mà nói với lý do tại sao họ không cung cấp cách để đếm các yếu tố).

Trân trọng, Dido

1

Mã của bạn không trả về phần tử từ phân phối đồng đều. Nó phụ thuộc vào thứ tự, luồng đó cung cấp các phần tử để giảm phương thức. Trong trường hợp chung, bạn không thể xem xét rằng thứ tự sẽ không phải là thứ tự đặc biệt. Giải quyết nhiệm vụ của bạn: nếu bạn có đủ bộ nhớ, bạn có thể viết RandomComparator (lưu các kết quả trước đó trong Bản đồ), sắp xếp luồng của bạn với bộ so sánh này và lấy phần tử đầu tiên (không sử dụng findAny). Nếu luồng quá lớn, có thể lấy mẫu bằng RandomFilter.

btw, nếu bạn có cờ SIZED trong luồng của mình, tác vụ là không đáng kể. Chỉ cần lấy kích thước, tạo ra chỉ số ngẫu nhiên và tạo spip :)

+0

Bạn có thể giải thích tại sao nó trả về một câu trả lời sai? Tôi đã không nghĩ về câu hỏi này trong một thời gian, nhưng tôi không hiểu tại sao thuật toán MapReduce lại tạo ra kết quả sai? –

Các vấn đề liên quan