2015-09-19 25 views
11

Bằng cách viết ứng dụng trong Java, có nhiều trường hợp sử dụng cho java.util.Collection. Kể từ khi java.util.stream.Stream được giới thiệu với Java 8, tôi đã gặp một số trường hợp sử dụng, nơi rất khó để quyết định sử dụng.Quyết định giữa việc sử dụng Luồng hoặc Vòng lặp

Ví dụ: Bạn sẽ viết một số phương pháp sử dụng.

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    return toFilter.stream() 
     .filter((Object o) -> hash == o.hashCode()) 
     .collect(Collectors.toCollection(LinkedList::new)); 
} 

gì về cách viết nó như thế này:

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    List<Object> result = new LinkedList<>(); 

    for(Object o : toFilter) { 
     if(hash == o.hashCode()) { 
      result.add(o); 
     } 
    } 

    return result; 
} 

Cả hai phương pháp sẽ tạo ra kết quả tương tự. java.util.stream.Streamjava.util.stream.Collector là các giao diện, do đó, việc triển khai cũng có thể khác nhau nếu tôi sử dụng các luồng tùy chỉnh và bộ sưu tập.

Tôi nghĩ rằng có vô số triển khai ngoài đó bằng cách sử dụng vòng lặp cũ fashoined.

Vì vậy, có thể trả lời những gì cần sử dụng, phát trực tiếp hoặc lặp lại, theo trường hợp sử dụng không? Và nếu có, tất cả các triển khai phải được cập nhật khi thích hợp không?

Hoặc tôi có nên cung cấp cả hai cách bằng cách triển khai các phương thức util? Hoặc tôi cũng nên cung cấp một người trả lại luồng sau quá trình lọc để bạn có thể làm việc với luồng đó nếu cần?

+0

Bạn có thể có song song thực sự dễ dàng với Luồng, chúng nhỏ gọn hơn (một số có thể nói "dễ đọc hơn") và có thêm lợi thế, nếu Luồng của bạn là "luồng" thực tế (thứ gì đó đang chảy, động) - không dựa trên bộ sưu tập cố định như ở đây). Nhưng trong trường hợp cụ thể của bạn, tôi nghĩ bạn có thể đi theo một trong hai cách. – mastov

+0

Vì vậy, chúng tôi có thể rút ngắn điều đó thành: Luồng sẽ được ưu tiên hơn, nhưng trong trường hợp sử dụng dễ dàng cả hai đều ổn chứ? – narranoid

+3

Tôi sẽ sử dụng hai quy tắc đơn giản: 1. nếu nó không bị hỏng, đừng sửa nó. 2. sử dụng những gì bạn thấy dễ đọc nhất và có thể bảo trì. Điều đó nói rằng, hai ví dụ của bạn không trả lại cùng một thứ: một trả về một ArrayList, và một ví dụ khác trả về một LinkedList. –

Trả lời

5

Lưu ý rằng trong quá trình triển khai, bạn sẽ kết hợp với loại thu thập kết quả cụ thể LinkedList thường có hiệu suất rất kém so với ArrayList. Điều gì xảy ra nếu người dùng phương pháp của bạn muốn sử dụng danh sách kết quả theo cách truy cập ngẫu nhiên? Có lẽ người dùng của phương thức này cần một mảng, vì nó phải được chuyển đến một phương thức API khác chấp nhận một mảng. Đôi khi người dùng chỉ cần biết có bao nhiêu đối tượng với hashCode đã có trong bộ sưu tập đầu vào, do đó không cần phải tạo danh sách kết quả nào cả. Cách Java-8 là để trở về con suối từ các phương pháp, không phải là các bộ sưu tập và để cho người gọi quyết định làm thế nào để thu thập nó:

public static <T> Stream<T> filterHashToList(int hash, Collection<T> toFilter) { 
    return toFilter.stream() 
     .filter(o -> hash == o.hashCode()); 
} 

Và sử dụng nó:

filterHashToList(42, input).count(); 

Hoặc

filterHashToList(42, input).collect(toCollection(ArrayList::new)); 

Hoặc

filterHashToList(42, input).toArray(); 

wa này y phương pháp trở nên rất đơn giản, vì vậy bạn có thể không cần nó chút nào, nhưng nếu bạn muốn thực hiện lọc/chuyển đổi có tính linh hoạt hơn, thì không sao cả.

Vì vậy, nếu bạn không muốn thay đổi API và vẫn trả lại LinkedList, bạn không cần phải thay đổi triển khai. Nhưng nếu bạn muốn tận dụng lợi thế từ việc sử dụng API luồng, tốt hơn là thay đổi loại trả về thành Stream.

8

Trong trường hợp không có câu trả lời đã đăng, tôi sẽ báo Brian Goetz là người phản ánh tình cảm của tôi và tôi nghi ngờ nhiều người khác '.

Không có gì kỳ diệu về luồng hoặc vòng lặp. Bạn nên viết mã có thể đọc được, rõ ràng và duy trì được. Một trong hai loại này có thể chấp nhận được.

0

Tôi nghĩ điều này phần lớn phụ thuộc vào kích thước dự kiến ​​của Bộ sưu tập và ứng dụng thực tế của chương trình. Trước đây là hơi hiệu quả hơn một chút, nhưng tôi thấy nó ít dễ đọc hơn và vẫn còn các hệ thống chạy trên Java 7 (tức là Google App Engine). Ngoài ra, sau này có thể dễ dàng hơn để thêm các bộ lọc phức tạp hơn để tiếp tục. Tuy nhiên, nếu hiệu quả là mối quan tâm chính, tôi sẽ đi với cái cũ.

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