Home > Software design >  Deep copy a LinkedList contained within an object?
Deep copy a LinkedList contained within an object?

Time:10-31

This is a project for school so don't give me the direct answer but please just point me in the right direction.

I'm making a generic deck of playing cards. I have a Card class, which works perfectly fine to make card objects. I also have a Deck class mostly working fine except I can't figure out how to use a copy constructor to deep copy one deck into a new deck. This is what I have now:

import java.util.LinkedList;

public class Deck {
    static LinkedList<Card> m_cards = new LinkedList<Card>();
    Card card;

    public Deck() {
        for(int i = 0; i <= 3; i  ) {
            for (int j = 2; j <= 14; j  ) {
                card = new Card(j, i);

                m_cards.add(card);
                System.out.println(card);
            }
        }
    }

    public Deck(Deck deck) {
        for(Card card : m_cards) {

        }
    }
    
    public String toString() {
        String cards = "";
        for (int i = 0; i < m_cards.size(); i  ) {
            cards  = m_cards.get(i)   ", ";
        }
        return cards   size(m_cards)   " total cards. ";
    }

    public int size(LinkedList<Card> list) {
        return list.size();
    }

    public static void main(String[] args) {
        Deck deck1 = new Deck();
        Deck deck2 = new Deck(deck1);

        System.out.println(deck1.toString());
        // System.out.println(deck2.toString());

    }
}
  1. I think what's tripping me up is I can't just say "for card in deck" because the deck isn't an iterable object but the linkedlist m_cards is. So essentially, I'm supposed to take a deck as the parameter but I don't see anything I can actually do with the deck.

  2. My instructions specifically say to make "A default constructor that initializes a fresh deck of 52 cards in the linked list", so should I be making a Deck of 52 Cards inside the linked list or does the linked list directly contain 52 cards (what I'm doing right now)?

Also, this is the output with just deck1 being printed:

2 of Hearts, 3 of Hearts, 4 of Hearts, 5 of Hearts, 6 of Hearts, 7 of Hearts, 8 of Hearts, 9 of Hearts, 10 of Hearts, Jack of Hearts, Queen of Hearts, King of Hearts, Ace of Hearts, 2 of Spades, 3 of Spades, 4 of Spades, 5 of Spades, 6 of Spades, 7 of Spades, 8 of Spades, 9 of Spades, 10 of Spades, Jack of Spades, Queen of Spades, King of Spades, Ace of Spades, 2 of Clubs, 3 of Clubs, 4 of Clubs, 5 of Clubs, 6 of Clubs, 7 of Clubs, 8 of Clubs, 9 of Clubs, 10 of Clubs, Jack of Clubs, Queen of Clubs, King of Clubs, Ace of Clubs, 2 of Diamonds, 3 of Diamonds, 4 of Diamonds, 5 of Diamonds, 6 of Diamonds, 7 of Diamonds, 8 of Diamonds, 9 of Diamonds, 10 of Diamonds, Jack of Diamonds, Queen of Diamonds, King of Diamonds, Ace of Diamonds, 52 total cards. 

If I print deck2, it just prints this twice. Which is kind of weird because I have no code in the copy constructor. Where is it getting this data from?

CodePudding user response:

First, if you want to copy one deck to another, you need to have the ability to have two decks. therefor, the linked list must be an instance variable (not static) so that each new Deck() will have its own list of cards.

Next step in copying a deck, is to be able to copy a card. so you need a copy constructor for a card, as well as a deck.
Deep copy means creating a new object with same properties as the source object. this is in contrast to shallow copy which creates a reference to the same object

shallow copy of a card is

Card sourceCard = new Card();
Card copyCard = sourceCard;

with shallow copy, the two card variables are references pointing to the same object. they share the properties. if you change the suit of one, it will affect the 2nd.

deep copy of a card is

Card sourceCard = new Card();
Card copyCard = new Card();
copyCard.suit = sourceCard.suit;
copyCard.rank = sourceCard.rank;

this way, two separate objects are created with two separate properties that have same initial values. if you change the suit of one, it will not affect the 2nd.
of course, this is exactly what copy constructor does:

public Card(Card sourceCard) {
    this.suit = sourceCard.suit;
    this.rank = sourceCard.rank;
}

so, the copy constructor of the deck should create a new list, then iterate on the list of the argument deck, create new card using the Card copy constructor, and put that new card in the list.

hint: start with amending the code to iterate on the (instance variable) list of the argument:

for(Card card : deck.m_cards) {
  • Related