2011-10-21 33 views
6

Ví dụ, tôi đã tập hợp các số liệu hình học:Làm thế nào để tạo bộ sưu tập từ Iterable trong java?

Set<Figure> figures; 

Có hai loại hình: Square và Circle.

Tôi muốn để có được thiết của hình vuông bằng bộ sưu tập google:

Iterables.filter(figures,squarePredicate); 

Nhưng phương pháp lọc trở lại Iterable ... Làm thế nào tôi có thể tạo các Set từ Iterable? (không sử dụng vòng lặp trên Iterable)

Trả lời

14

Tôi nghĩ bạn cần phải suy nghĩ lại các yêu cầu của mình. Bạn cần một tập các ô vuông. Tại sao?

Một tập hợp cung cấp cho bạn tính độc đáo và lặp lại, không có gì khác. Bạn có duy nhất trong Iterable của bạn, bởi vì nguồn là một tập hợp, và bạn có thể lặp qua các mục trong một Iterable. Vậy tại sao bạn cần bộ này?

Chỉ có hai lý do có thể có: bạn đang làm việc với API cần tham số Set (hoặc Collection) hoặc bạn cần bằng cách nào đó hiển thị kích thước của Set. Trong các trường hợp này, hãy sử dụng Sets.newHashSet(iterable) để tạo một Set (một mặt tất nhiên đòi hỏi một lần lặp lại đầy đủ, mặt khác: bạn sẽ cần lặp lại đầy đủ tại một thời điểm nào đó khi bạn đang lặp qua các giá trị, vì vậy, tại sao không làm điều đó bây giờ?). Nếu không, chỉ cần sử dụng Iterable và quên về một Set.

+0

Mã này là ví dụ. Tôi đã thiết lập các đối tượng của hai loại. Tôi muốn lọc một loại đối tượng với các bộ sưu tập của google, và sau đó nhận được loại đối tượng thứ hai với bộ nền. –

+0

Lỗi đánh máy nhỏ: Sets.newHash ** S ** et (có thể lặp lại) – tashuhka

+0

@tashuhka đã sửa, cảm ơn –

1

Có thể thử CollectionUtils.filter() từ utils collection utils thay thế? Bạn có thể sử dụng nó trên một Set, hoặc sử dụng tập hợp kết quả trong Set constructor.

+0

OP đã loại nhà nước "sử dụng Google Bộ sưu tập ". –

+0

Câu hỏi đặt ra là về ổi, không phải là Commons/Collections. Và vấn đề là như nhau: bạn cần lặp lại đầy đủ để áp dụng bộ lọc. –

+0

Tôi tin rằng anh ấy đang mô tả vấn đề anh ấy đang gặp phải với bộ sưu tập của google thay vì nói rằng đó là bắt buộc để sử dụng nó. Tôi chỉ đề nghị đi một hướng khác trong trường hợp nó không phải là bắt buộc. Chỉ là một gợi ý. – kgautron

5

Sốcủa ổi cố ý trả về "chế độ xem" có thể lặp lại. Có hai lợi ích cho phương pháp này:

  • bạn chỉ lặp qua các phần tử khi bạn thực sự cần (ví dụ: bạn có thể gọi các lệnh Iterables.filter() và Iterables.transform() và chỉ lặp lại một lần ở cuối).
  • bạn có thể tạo bộ sưu tập thích hợp từ xem, sử dụng một cái gì đó giống như ImmutableSet.copyOf(Iterables.filter(..., ...)), Sets.newHashSet(Iterables.filter(..., ...)), hoặc Lists.newArrayList(Iterables.filter(..., ...)). Iterables.filter() cho phép bạn chọn bộ sưu tập chính xác cần thiết, thay vì trả lại một tùy ý.

Tôi cũng nhận thấy rằng bạn dường như sử dụng Iterables.filter(Iterable unfiltered, Predicate predicate) với một vị để lọc các trường hợp của một loại hình cụ thể. Bạn cũng có thể quan tâm đến quá tải Iterables.filter(Iterable unfiltered, Class type), bộ lọc này sẽ lọc tất cả các phiên bản của loại đã cho và trả về một Iterable với loại chung chung cụ thể hơn. Điều này cho phép bạn tránh các phôi vụng về.

+0

cảm ơn! rất thông tin –

7

Nếu bạn có số Set, bạn có thể sử dụng Sets.filter thay vì Iterables.filter và nhận kết quả Set. Đó Set là một cái nhìn trực tiếp, như là kết quả của Iterables.filter, nhưng nó có Set tính như một contains phương pháp nhanh chóng.

Để tạo một bản sao chỉ chứa các phần tử phù hợp với vị từ, bạn có thể sử dụng ImmutableSet.copyOf hoặc Sets.newHashSet như những người khác đã đề xuất.

1

Bạn có thể lọc một tập và thu thập vào một bộ với Java 8 suối:

Set<Number> integers = numbers.stream() 
    .filter(x -> x instanceof Integer) 
    .collect(Collectors.toSet()); 

Tập trở lại là một bản sao, không phải là một live view.

Lưu ý rằng không giống như, ví dụ: Số FluentIterable.filter của ổi, tập kết quả là Set<Integer> vì Java không biết bạn đã lọc ra tất cả các số nguyên không. Nếu bạn cần số Set<Integer>, you have to map after filtering.

Set<Integer> integers = numbers.stream() 
    .filter(x -> x instanceof Integer) 
    .map(x -> (Integer)x) 
    .collect(Collectors.toSet()); 

(Bạn có thể kết hợp các bộ lọc và bản đồ thành một flatMap, nhưng điều đó sẽ giới thiệu một dòng đối tượng tạm thời mỗi số nguyên, và không phải là bất kỳ súc tích hơn.)

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