tobloef
tobloef

Reputation: 1891

Creating lists from atributes of objects in a list

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!

Upvotes: 1

Views: 63

Answers (2)

Binkan Salaryman
Binkan Salaryman

Reputation: 3058

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

Upvotes: 1

Eran
Eran

Reputation: 394146

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());

Upvotes: 1

Related Questions