2017-02-27 5 views
1

C'est la même question publiée here mais en Java, puisque dans C# yield résoudrait mon problème.Comment obtenir chaque paire non ordonnée d'éléments, sans répétition de deux listes paresseusement?

Exemple: si vous avez [1,2] [5,6]. Je voudrais obtenir [1,5] [1,6] [2,5] [2,6]

Mais si je n'ai qu'une liste [1,2,3] le résultat serait [1, 2] [1,3] [2,3]

C'est ce que j'ai:

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; 
} 

Je veux juste faire la méthode paresseuse. Des idées?

+1

Il est difficile de créer un paresseux 'Collection'. Est-ce que Iterable ou Iterator suffirait? – shmosel

+0

@shmosel C'est exactement ce que je cherchais. –

Répondre

2

Il est très compliqué de créer un Collection paresseux qui soutiendrait add(), remove() etc. Mais vous pouvez retourner facilement un Iterator (qui est par nature paresseux) à l'aide de flux:

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(); 
} 

ci-dessus peuvent être facilement convertis en un Iterable si on le souhaite:

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

Très belle réponse, +1 pour l'utilisation de 'flatMap (Function.identity())'. Conduit à un problème de discordance de type avec le compilateur Eclipse mais est facilement corrigé en ajoutant '>' juste avant le 'mapToObj' interne et après le point. –

+0

@MarkusBenko Travaillé pour moi dans Eclipse avec 'AbstractMap.SimpleEntry'. – shmosel

+0

Étrange. Copié et collé votre code, ajouté une implémentation Entry simple avec le constructeur de deux-args et Eclipse 4.4.2 et jette l'erreur suivante ici: 'Type discordance: ne peut pas convertir de Iterator à Iterator >'. –

0

L'approche proposée par iterator @shmosel est une bonne idée, voici mon:

Pour que cela fonctionne pour une seule liste, les listes entrantes doivent être égales. Par exemple 1,2,3 et 1,2,3 produira:

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(); 
}