1

I wish I could be more concise in my title, but I'm not quite sure how to describe what I want to do. I have a list containing a number of objects of a class I've made. Each object has a number of attributes, accessible by some getters and setters. I would like to create a list for each attribute, get the attributes of each object and put them into their respective lists.

I'm currently doing this with the code below:

ArrayList<Integer> counts = new ArrayList<Integer>();
ArrayList<String> colors = new ArrayList<String>();
ArrayList<String> shapes = new ArrayList<String>();
ArrayList<String> fills = new ArrayList<String>();

for (Card card: cards) {
    counts.add(card.getCount());
    colors.add(card.getColor());
    shapes.add(card.getShape());
    fills.add(card.getFill());
}

But I'm wondering if there's a shorter, maybe better, way to do this? Or am I doing it the "proper" already? Thanks!

4
  • 2
    i am curious: why do you want to do this? why is storing attributes separated in several lists better than storing objects containing attributes in one list? Commented Dec 2, 2015 at 10:08
  • Perhaps there's a better solution for what I want to do. I would like to check if each list of attributes contains either completely different elements, or completely identical elements. Commented Dec 2, 2015 at 10:14
  • Looks like you need to develop a set game as homework... Commented Dec 2, 2015 at 10:52
  • Not quite. I'm making a set solver using OpenCV (which, if you don't know, is a computer vision library). I think it would be cool to be able to point my phone's camera at a table of cards and instantly get the solution. Commented Dec 2, 2015 at 12:49

2 Answers 2

1

Your way looks fine. You can write it with less lines of code if you use Java 8 Streams, but that would require 4 iterations over the cards list instead of the single iteration you currently have.

For example, to create the list of counts, you can write :

List<Integer> counts = cards.stream().map(Card::getCount).collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

3 Comments

This just the kind of thing I was looking for. I'm probably not going to use this code, as it isn't very easy to read, but it's nice to know that you can do it another way.
@TobLoef I suggest you read about the Streams API and lambda expressions. It might be useful for you one day, so getting used to that syntax is a good idea. Once you get used to it, you might change your mind regarding whether it's easy to read or not.
Will definitely do. Thanks!
1

If you are developing a set game, here is a solution for checking and completing card sets:

Card.java:

import java.util.Locale;

public final class Card {
    public static void main(String[] args) {
        Card a = new Card(Count.ONE, Color.RED, Fill.STRIPED, Shape.DIAMOND);
        Card b = new Card(Count.TWO, Color.RED, Fill.SOLID, Shape.DIAMOND);
        Card c = completeSet(a, b);
        System.out.println(c);
    }

    public int count;
    public int color;
    public int fill;
    public int shape;

    public Card() {

    }

    public Card(Count count, Color color, Fill fill, Shape shape) {
        setCount(count);
        setColor(color);
        setFill(fill);
        setShape(shape);
    }

    // getters and setters to operate with the attribute enumerations
    public Count getCount() {
        return Count.values()[count];
    }

    public Color getColor() {
        return Color.values()[color];
    }

    public Shape getShape() {
        return Shape.values()[shape];
    }

    public Fill getFill() {
        return Fill.values()[fill];
    }

    public void setCount(Count count) {
        this.count = count.ordinal();
    }

    public void setColor(Color color) {
        this.color = color.ordinal();
    }

    public void setShape(Shape shape) {
        this.shape = shape.ordinal();
    }

    public void setFill(Fill fill) {
        this.fill = fill.ordinal();
    }

    public static int completeAttribute(int a, int b) {
        if (a == b) {
            // attribute for each same
            return a;
        } else {
            // attribute for each different
            int c;
            for (c = 0; c < 3; c++) {
                if (c != a && c != b) {
                    break;
                }
            }
            return c;
        }
    }

    public static Card completeSet(Card a, Card b) {
        // determine missing card to make a set
        Card result = new Card();
        result.count = completeAttribute(a.count, b.count);
        result.color = completeAttribute(a.color, b.color);
        result.shape = completeAttribute(a.shape, b.shape);
        result.fill = completeAttribute(a.fill, b.fill);
        return result;
    }

    public static boolean isSet(Card a, Card b, Card c) {
        // check if it is a set by completing it
        return completeSet(a, b).equals(c);
    }

    @Override
    public boolean equals(Object that) {
        // currently unused
        if (this == that) {
            return true;
        }
        return that != null && that instanceof Card && this.equals((Card) that);
    }

    public boolean equals(Card that) {
        if (this == that) {
            return true;
        }
        return that != null
                && this.color == that.color
                && this.count == that.count
                && this.fill == that.fill
                && this.shape == that.shape;

    }

    @Override
    public int hashCode() {
        // currently unused
        int result = count;
        result = 31 * result + color;
        result = 31 * result + shape;
        result = 31 * result + fill;
        return result;
    }

    @Override
    public String toString() {
        // pretty print attributes
        String result = getCount() + " " + getColor() + " " + getFill() + " " + getShape();
        result = result.toLowerCase(Locale.ROOT);
        if(getCount() != Count.ONE) {
            result += "s";
        }
        return result;
    }

    // enumerations for pretty names
    public enum Count {
        ONE,
        TWO,
        THREE
    }

    public enum Color {
        RED,
        GREEN,
        VIOLET
    }

    public enum Shape {
        ELLIPSE,
        DIAMOND,
        TWIRL
    }

    public enum Fill {
        OPEN,
        STRIPED,
        SOLID
    }
}

Output: three red open diamonds

2 Comments

While you're right in guessing that I'm developing something to do with SET, this doesn't really answer my question. Thanks for posting the code though, I'll have a look at your implementation to see how it differs from how I would do it.
@TobLoef Yes, you're right. This isn't actually an answer to your question. But keeping the attributes as primitives should get you an idea on how to deal with them most easily. Your Lists of Card properties could be defined as: int[/*4*/][/*cards count*/] or List<int[/*4*/]>.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.