Performance/Optimization of Knapsack(ish) algorithm for move generation for a game
In your recursive generateMoves method, you can reduce a huge amount of the duplicates by limiting where in the centerCards list you operate in.

My suggestion would be to pass that list through the recursion with a pointer to your current position in the array.... for example:

generateMoves(Card myCard,ArrayList&lt;Card&gt; CurrentMove,
          ArrayList&lt;Card&gt; centerCards, int centercardpos,
          ArrayList&lt;Move&gt; moves, int moveSum)


Then, in your method you can change the loop:

for (Card card :centerCards) { ...


to be:

for (int ci = centercardpos; ci &lt; centerCards.size(); ci++) {
    Card card = centerCards.get(i);

        generateMoves(myCard, CurrentMove, centerCards,
               centercardpos + 1, // new increased limit.....
               moves, moveSum);


This will substantially reduce the number of possible moves (and still get the right answers). Reducing the values you gnerate will also substantially reduce duplicates, which in turn will also improve th pwerformance of removeDuplicates ...

The only time removeDuplicates will have effect is when you have something like (using your example: [5,4,3,2,1,2] ) the moves [5,2] and [5,2] (but the 'other' 2).