2017-02-27 256 views
1

這是發佈here但在Java中的相同問題,因爲在C#中,yield會解決我的問題。如何獲得每一個無序的元素對,而不用重複從兩個列表中懶得?

例如:如果有[1,2] [5,6]。我想得到[1,5] [1,6] [2,5] [2,6]

但是,如果我只有一個列表[1,2,3],結果將是[1, 2] [1,3] [2,3]

這是我有:

public static <T,K> Collection<Entry<T,K>> Pairs (List<T> l1, List<K> l2) 
{ 
    Collection<Entry<T,K>> result = new LinkedList<>(); 

    for(int i =0;i<l1.size();i++) 
    { 
     for(int j=(l1==l2?i+1:0);j<l2.size();j++) 
     { 
      result.add(new Entry<>(l1.get(i),l2.get(j))); 
     } 
    } 
    return result; 
} 

我只是想方法懶惰。有任何想法嗎?

+1

這不是容易地創建一個懶惰'Collection'。 Iterable或Iterator足夠嗎? – shmosel

+0

@shmosel這就是我正在尋找的。 –

回答

2

這是非常複雜的,以創建一個懶惰的Collection將支持add()remove()等,但你可以很容易地返回Iterator(這是天生懶惰)使用流:

public static <T, K> Iterator<Entry<T, K>> pairs(List<T> l1, List<K> l2) { 
    return IntStream.range(0, l1.size()) 
      .mapToObj(i -> IntStream.range(l1 == l2 ? i + 1 : 0, l2.size()) 
        .mapToObj(j -> new Entry<>(l1.get(i), l2.get(j)))) 
      .flatMap(Function.identity()) 
      .iterator(); 
} 

上面可以很容易地轉換成一個Iterable如果需要的話:

Iterable<Entry<T, K>> iterable =() -> pairs(l1, l2); 
+0

非常好的答案,使用'flatMap(Function.identity())'+1。導致與Eclipse編譯器的類型不匹配問題,但可以通過在內部'mapToObj'之前和點之後添加'>來輕鬆解決。 –

+0

@MarkusBenko用'AbstractMap.SimpleEntry'在Eclipse中爲我工作。 – shmosel

+0

奇怪。複製並粘貼你的代碼,添加一個帶有兩個參數構造函數和Eclipse 4.4.2的簡單Entry實現,並在這裏拋出以下錯誤:'類型不匹配:不能從Iterator 轉換爲Iterator ''。 –

0

通過@shmosel提出的迭代方法是一個好主意,這是我的看法:

爲了使其適用於單個列表,傳入列表必須相同。例如1,2,31,2,3和將產生:

1 = 2 1 = 3 2 = 3

public static Iterator<AbstractMap.SimpleEntry<Integer, Integer>> test(List<Integer> left, List<Integer> right) { 

    return IntStream.range(0, left.size()).boxed().flatMap(i -> left.equals(right) 
      ? left.stream().skip(i + 1).map(j -> new AbstractMap.SimpleEntry<>(left.get(i), j)) 
      : right.stream().map(j -> new AbstractMap.SimpleEntry<>(left.get(i), j))) 
      .iterator(); 
} 
相關問題