2010-02-22 46 views
27

Giả sử tôi có một danh sách (hoặc Set):lọc và sắp xếp danh sách sử dụng các bộ sưu tập google

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB"); 

Tôi muốn nhận lại một ImmutableList (Set) mà các loại/nhóm điều khoản trong trật tự tự nhiên nơi các từ bắt đầu với "src" trước tiên, "assoc" thứ hai và "dest" cuối cùng. Nếu một thuật ngữ không chứa những từ đó thì nó sẽ bị loại bỏ khỏi danh sách kết quả.

Do đó, kết quả ở đây là "srcB", "srcT", "assocX", "destA".

Tôi nghĩ rằng tôi có thể làm điều này với một số kết hợp của Iterables.filter hoặc Predicates nhưng chỉ không nhìn thấy nó. Phải có một cách ngắn gọn để làm điều đó tôi nghĩ.

CHỈNH SỬA: Một bộ ở vị trí của danh sách cũng hoạt động.

Trả lời

32

Chừng nào những ba tiền tố là những điều duy nhất bạn quan tâm, tôi muốn đề nghị một cái gì đó như thế này:

Predicate<String> filter = new Predicate<String>() { 
     @Override 
     public boolean apply(String input) { 
      return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest"); 
     } 
    }; 

    Function<String, Integer> assignWeights = new Function<String, Integer>() { 
     @Override 
     public Integer apply(String from) { 
      if (from.startsWith("src")) { 
       return 0; 
      } else if (from.startsWith("assoc")) { 
       return 1; 
      } else if (from.startsWith("dest")) { 
       return 2; 
      } else { 
       /* Shouldn't be possible but have to do something */ 
       throw new IllegalArgrumentException(from + " is not a valid argument"); 
      } 
     } 
    }; 

    ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
      Ordering.natural().onResultOf(assignWeights).sortedCopy(
        Iterables.filter(testList, filter) 
      ) 
    ); 

Giải pháp này chắc chắn sẽ không quy mô ra vô cùng tốt nếu bạn bắt đầu thêm nhiều tiền tố để lọc ra hoặc sắp xếp theo, vì bạn phải liên tục cập nhật cả bộ lọc và trọng lượng của từng tiền tố.

+11

Trong các trường hợp khác, tốt hơn là 'ném mới IllegalArgumentException() 'hơn' trả về 3'. –

0

Tôi nghĩ rằng trước tiên bạn sẽ sử dụng biến vị ngữ để loại bỏ các yếu tố bạn không muốn và triển khai Comparator và sắp xếp danh sách của bạn.

12

Hãy xem This Google Collections example.

Function<Fruit, String> getNameFunction = new Function<Fruit, String>() { 
    public String apply(Fruit from) { 
     return from.getName(); 
    } 
}; 

Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction); 

ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
    nameOrdering).addAll(fruits).build(); 

Mặc dù điều này, được thừa nhận, trả về Tập hợp.

0

Thông thường, đó là thiết kế tồi để đối chiếu dữ liệu riêng biệt rõ ràng như thế này. Trong trường hợp của bạn, khi bạn nói "assocX", "assoc" có một ý nghĩa riêng biệt từ "X", nhưng bạn hợp nhất chúng với nhau.

Vì vậy, tôi khuyên bạn nên thiết kế một lớp học với hai trường. Sau đó, bạn có thể tạo thứ tự trên trường đầu tiên, một thứ tự khác trên thứ hai và kết hợp chúng (ví dụ: Ordering # compound()). Với phương thức toString() mà làm hợp nhất các trường này thành một chuỗi. Như một phần thưởng, điều này có thể làm giảm đáng kể việc sử dụng bộ nhớ thông qua chia sẻ.

Vì vậy, bạn sẽ sắp xếp danh sách các đối tượng như vậy và nếu bạn muốn in chúng, bạn chỉ cần gọi toString() trên chúng.

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