How to get certain values from ArrayList and put them in a map

Solution for How to get certain values from ArrayList and put them in a map
is Given Below:

I have a program where there are 52 cards and int number of players (for example lets start from 4), the task is asking me to put elements like this in a map of Map<String, List>:

{Player 1=[51, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11, 7, 3], " +
"Player 2=[50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2], " +
"Player 3=[49, 45, 41, 37, 33, 29, 25, 21, 17, 13, 9, 5, 1], " +
"Player 4=[48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0]}")

I have written the logic like this:

Map<String, List<Card>> myMap = new HashMap<>();
for(int i=0; i<players; i++){
    myMap.put("Player " + i, ///here i don't know how to put these values;
}

Any suggestions how to put those List in the map according to the task?

I reckon you want to ‘distribute’ the cards among players. You can use something like this per player:

first player 51 - 4 * i
second player 50 - 4 * i
third player 49 - 4 * i
fourth player 48 - 4 * i

where i runs from 0 to 12 inclusive.

Here is one approach.

  • generate 1 to n players via an IntStream
  • using the current player #, generate a map entry to hold the player, and the list.
    • the list is constructed by iterating from 52-player #, in increments of number of # of players, again using an IntStream
    • The number is then mapped to a Card instance and stored in the list.
  • Then the player number and list are transfer to a LinkedHashMap (I chose the map type to visually show the order in which the values were added).

The Card class

class Card {
    public int v;
    public Card(int v) {
        this.v = v;
    }
    @Override
    public String toString() {
        return v+"";
    }
}

The main code


int nPlayers = 4;
Map<String, List<Card>> map = IntStream.rangeClosed(1, nPlayers)
        .mapToObj(
                player -> new AbstractMap.SimpleEntry<String, List<Card>>(
                        "Player" +player,
                        IntStream.iterate(52 - player,
                                i -> i >= 0, i -> i -= nPlayers)
                                .mapToObj(Card::new)
                                .toList()))
        .collect(Collectors.toMap(Entry::getKey,
                Entry::getValue,
                (a,b)->a,             // may be removed if 
                LinkedHashMap::new)); // map type not relevant.

map.entrySet().forEach(System.out::println);

For four players, prints

Player1=[51, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11, 7, 3]
Player2=[50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2]
Player3=[49, 45, 41, 37, 33, 29, 25, 21, 17, 13, 9, 5, 1]
Player4=[48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0]

Having written the streams approach here is a more conventional approach which is probably more efficient and easier to understand.

Map<String, List<Card>> map2 = new LinkedHashMap<>();
for (int i = 1; i <= nPlayers; i++) {
    List<Card> list = new ArrayList<>();
    for (int c = 52-i; c >= 0; c -= nPlayers) {
        list.add(new Card(c));
    }
    map2.put("Player" + i, list);
}

Since cannot figure out what exactly is needed, maybe this could be helpful.

public class TestAddMap {

    public static void main(String[] args)
    {
        Map<String, List<Integer>> map = new HashMap<>();
        int numberOfPlayers = 4;
        
        for(int i=1;i<=numberOfPlayers;i++)
        {
            Player p=new Player("player_"+i);
            //construct player_n list
            for(int j=1;j<=52;j++)
            {
                if((j-i)%numberOfPlayers==0)
                {
                    p.getList().add(j);
                }
                //even if the result is fine it's better to add line after for_loop
                //being here is just update old entries
                map.put(p.name,p.list);
            }
            //add entry when list for player_n is fully populated
            //map.put(p.name,p.list);
        }
        
        map.forEach((k,v)->System.out.println(k+":"+v));
        
    }
    static class Player
    {
        String name;
        List<Integer> list=new ArrayList<Integer>();
        Player(String name)
        {
            this.name=name;
        }
        
        public List<Integer> getList()
        {
            return list;
        }
        
        public String toString()
        {
            return list.stream().
                        map(i->String.valueOf(i)).
                        collect(Collectors.joining(","));
        }
    }
}

Output:

numberOfPlayers = 4
player_1:[1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49]
player_4:[4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52]
player_3:[3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51]
player_2:[2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50]

numberOfPlayers = 3
player_1:[1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52]
player_3:[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51]
player_2:[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50]

etc.

Note:
Construct player_n list can be optimized with

//loop will skip directly values which not belong to player_n 
for(int j=i;j<=52;j=j+numberOfPlayers)
{
    p.getList().add(j); 
}