重複順列

要素の重複有りの順列(Permutation)Java で、いろんなオブジェクトに対して作成できるようにする。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * RepeatablePermutation
 */
public class RepeatablePermutation<T>{
   private int r, u;
   private int[] c;
   private int[] p;
   private List<List<T>> result;
   private List<T> list;

   private RepeatablePermutation(List<T> list){
      this.list = list;
      c = new int[list.size()];
      p = new int[list.size()];
      for(int i=0; i < c.length; i++) c[i] = i;
   }

   public static <T> RepeatablePermutation<T> of(List<T> list){
      return new RepeatablePermutation<>(list);
   }

   public static <T> RepeatablePermutation<T> of(T[] ary){
      return new RepeatablePermutation<>(Arrays.asList(ary));
   }

   public List<List<T>> compute(int len){
      if (len > list.size()) throw new IllegalArgumentException("list size over");
      result = new ArrayList<>();
      r = len;
      u = c[c.length-1] - len;
      for(int i=0; i <= c.length; i++)
         calc(0, i);
      return result;
   }

   private void calc(int i, int j){
      p[i] = j;
      if (i == r - 1){
         List<T> t = new ArrayList<>();
         for(int k=0; k < r; k++){
            if (p[k] < c.length)
               t.add(list.get(c[p[k]]));
         }
         if (t.size()==r)
            result.add(t);
      }
      if (i < r - 1){
         int k=0;
         for(; k <= r;k++)
            calc(i+1, k);
         if (u > 0){
            for(int n=0; n < u; n++)
               calc(i+1, c[k + n] );
         }
      }
   }
}

サンプル
文字列 "A", "B", "C”, "D" から、3個の順列(重複あり)

RepeatablePermutation<String> r = RepeatablePermutation.of(Arrays.asList("A", "B", "C", "D"));
r.compute(3).stream()
.map(e->e.stream().collect(Collectors.joining("")))
.forEach(System.out::println);

整数の場合

RepeatablePermutation<Integer> r = RepeatablePermutation.of(Arrays.asList(0, 1, 2, 3, 4));
r.compute(3).stream()
.map(e->e.stream().map(i->i.toString()).collect(Collectors.joining("")))
.forEach(System.out::println);