Strings from ArrayList to individual strings JAVA

Is there a way to "extract" individual strings from an ArrayList? I have stored strings in an ArrayList and want to print them to the console. I know that I can use a for-loop but it isn't quite that simple. I'm trying to create a column based print and I use a method (Created by "CandiedOrange" here on stack overflow) that takes strings separated by commas as input.

What it basically does is; It creates column spacing based on the length of strings in each column. (All credit to "CandiedOrange")

List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;

public Columns addLine(String... line) {

    if (numColumns == -1){
        numColumns = line.length;
        for(int i = 0; i < numColumns; i++) {
            maxLengths.add(0);
        }
    }

    if (numColumns != line.length) {
        throw new IllegalArgumentException();
    }

    for(int i = 0; i < numColumns; i++) {
        maxLengths.set(  i, Math.max( maxLengths.get(i), line[i].length() )  );
    }

    lines.add( Arrays.asList(line) );

    return this;
}

The number of columns I want to print is unknown during compile time because the user enters the number of columns 1-5 during run time. So I figured I could use ArrayLists for the rows and use the addLine() method with each of the arraylists for the rows.

If there Is a better way of solving this, I'd be more than happy to know.

EDIT:

From the start:

I'm creating a Yahtzee game with 1-5 players. Each Player is defined by instances of the class "Player"

public class Player {

private String name;

private int ones;
private int twos;
private int threes;
private int fours;
private int fives;
private int sixes;

private int threeofakind;
private int fourofakind;
private int fullhouse;
private int smallstraight;
private int largestraight;
private int chance;
private int yahtzee;

private int totalscore;

public int getOnes() {
    return ones;
}

public void setOnes(int ones) {
    this.ones = ones;
}

public int getTwos() {
    return twos;
}

public void setTwos(int twos) {
    this.twos = twos;
}

public int getThrees() {
    return threes;
}

public void setThrees(int threes) {
    this.threes = threes;
}

public int getFours() {
    return fours;
}

public void setFours(int fours) {
    this.fours = fours;
}

public int getFives() {
    return fives;
}

public void setFives(int fives) {
    this.fives = fives;
}

public int getSixes() {
    return sixes;
}

public void setSixes(int sixes) {
    this.sixes = sixes;
}

public int getThreeofakind() {
    return threeofakind;
}

public void setThreeofakind(int threeofakind) {
    this.threeofakind = threeofakind;
}

public int getFourofakind() {
    return fourofakind;
}

public void setFourofakind(int fourofakind) {
    this.fourofakind = fourofakind;
}

public int getFullhouse() {
    return fullhouse;
}

public void setFullhouse(int fullhouse) {
    this.fullhouse = fullhouse;
}

public int getSmallstraight() {
    return smallstraight;
}

public void setSmallstraight(int smallstraight) {
    this.smallstraight = smallstraight;
}

public int getLargestraight() {
    return largestraight;
}

public void setLargestraight(int largestraight) {
    this.largestraight = largestraight;
}

public int getChance() {
    return chance;
}

public void setChance(int chance) {
    this.chance = chance;
}

public int getYahtzee() {
    return yahtzee;
}

public void setYahtzee(int yahtzee) {
    this.yahtzee = yahtzee;
}

public int getTotalscore() {
    return totalscore;
}

public void setTotalscore(int totalscore) {
    this.totalscore = totalscore;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

I'm implementing MVC structure (to the best of my ability) which means that I have a View class with a method to display the main console column scoreboard. (Method unfinished)

public void displayMainScoreBoard(ArrayList<Player> playerList) {

    Columns col = new Columns();                                //Instance of column class.

    ArrayList<String> Name = new ArrayList<>();
    ArrayList<Integer> Ones = new ArrayList<>();
    ArrayList<Integer> Twos = new ArrayList<>();
    ArrayList<Integer> Threes = new ArrayList<>();
    ArrayList<Integer> Fours = new ArrayList<>();
    ArrayList<Integer> Fives = new ArrayList<>();
    ArrayList<Integer> Sixes = new ArrayList<>();

    ArrayList<Integer> Threeofakind = new ArrayList<>();
    ArrayList<Integer> Fourofakind = new ArrayList<>();
    ArrayList<Integer> Fullhouse = new ArrayList<>();
    ArrayList<Integer> Smallstraight = new ArrayList<>();
    ArrayList<Integer> Largestraight = new ArrayList<>();
    ArrayList<Integer> Chance = new ArrayList<>();
    ArrayList<Integer> Yahtzee = new ArrayList<>();

    ArrayList<Integer> Totalscore = new ArrayList<>();

    for (Player p : playerList) {                           //For every player, append their category data.
        Name.add(p.getName());
        Ones.add(p.getOnes());
        Twos.add(p.getTwos());
        Threes.add(p.getThrees());
        Fours.add(p.getFours());
        Fives.add(p.getFives());
        Sixes.add(p.getSixes());

        Threeofakind.add(p.getThreeofakind());
        Fourofakind.add(p.getFourofakind());
        Fullhouse.add(p.getFullhouse());
        Smallstraight.add(p.getSmallstraight());
        Largestraight.add(p.getLargestraight());
        Chance.add(p.getChance());
        Yahtzee.add(p.getYahtzee());
        Totalscore.add(p.getTotalscore());
    }

}

And heres CandiedOrange's full Column class. (Again, I claim no rights to his code.)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Columns {

List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;

public Columns addLine(String... line) {

    if (numColumns == -1){
        numColumns = line.length;
        for(int i = 0; i < numColumns; i++) {
            maxLengths.add(0);
        }
    }

    if (numColumns != line.length) {
        throw new IllegalArgumentException();
    }

    for(int i = 0; i < numColumns; i++) {
        maxLengths.set(  i, Math.max( maxLengths.get(i), line[i].length() )  );
    }

    lines.add( Arrays.asList(line) );

    return this;
}

public void print(){
    System.out.println( toString() );
}

public String toString(){
    String result = "";
    for(List<String> line : lines) {
        for(int i = 0; i < numColumns; i++) {
            result += pad( line.get(i), maxLengths.get(i) + 1 );
        }
        result += System.lineSeparator();
    }
    return result;
}

private String pad(String word, int newLength){
    while (word.length() < newLength) {
        word += " ";
    }
    return word;
}

}

How can I pass the Strings of my ArrayLists in my view to the addLine() Method?

Answers


I believe you should not be using that Columns class at all.

Most of your lists are numbers rather than strings. Numbers are best displayed right-justified. And the only string you have in each of the rows you want to display is the player name.

So instead of copying all the data to various lists, and assuming that for most of the numbers you have a reasonable width that they will not pass (4 digits? 6 digits?), then your task becomes:

  • Find the longest name in the list
  • Display each player such that the name is padded to accomodate the longest name found.

You could add these as methods to the Player class, so finding the maximal name length of a given list of players:

public static int maxNameLength( List<? extends Player> players ) {
    int maxLength = 0;
    for ( Player player : players ) {
        int currLength = player.getName().length();
        if ( currLength > maxLength ) {
            maxLength = currLength;
        }
    }
    return maxLength;
}

Now, displaying the current player in a properly padded way can be done using String.format, which uses a Formatter.

For the sake of brevity, suppose I just want to display the name, Yahtzee and total score. You'll have a method like this in Player:

public String getScoreLine( int maxLength ) {

    String format = "%-" + maxLength + "s %6d %6d";

    return String.format( format, getName(), getYahtzee(), getTotalscore() );
}

What the first part does is create a left-justified field for the string. So if maxLength is, say, 20, the format will be %-20s %6d %6d. The numbers will be displayed right-justified in fields 6 characters wide, the name, left-justified and padded to 20 characters.

Now you can loop on your list and display it like:

int maxNameLength = Player.maxNameLength( playerList );
for ( Player p : playerList ) {
    System.out.println( p.getScoreLine( maxNameLength ) );
}

Note: if you want to put the getScoreLine method in your View rather than in the Player class (since you are trying to do MVC), you will need to give it the player as a parameter.


...that takes strings separated by commas as input.

Technically, it takes an array (more in this Java tutorial on varargs). But Java lets you create that array automatically when calling it with discrete arguments.

Since it accepts an array, and you have an ArrayList, you can easily get an array to pass to it, using toArray(T[]):

List<List<String>> linesToAdd = /*...*/;
// ...
for (List<String> line : linesToAdd) {
    addLine(line.toArray(new String[line.size()]));
}

That said, it would be trivial (and a good coding exercise) to modify addLine to accept List<String> directly.


I followed the advice not to use the column class, even though I'd like to have tried using it. I semi-hardcoded the solution.

playerList is the list of players present in the game. and categories is obtained from another class to check which categories are pickable when scoring. (Displayed as X when unavailable and O when pickable.)

public void displayMainScoreBoard(ArrayList<Player> playerList, ArrayList<Boolean> categories) {

    List<String> Name = new ArrayList<>();
    List<String> Ones = new ArrayList<>();
    List<String> Twos = new ArrayList<>();
    List<String> Threes = new ArrayList<>();
    List<String> Fours = new ArrayList<>();
    List<String> Fives = new ArrayList<>();
    List<String> Sixes = new ArrayList<>();

    List<String> Threeofakind = new ArrayList<>();
    List<String> Fourofakind = new ArrayList<>();
    List<String> Fullhouse = new ArrayList<>();
    List<String> Smallstraight = new ArrayList<>();
    List<String> Largestraight = new ArrayList<>();
    List<String> Chance = new ArrayList<>();
    List<String> Yahtzee = new ArrayList<>();

    List<String> Totalscore = new ArrayList<>();

    for (Player p : playerList) {                           //For every player, append their category data.
        Name.add(p.getName());
        Ones.add(String.valueOf(p.getOnes()));
        Twos.add(String.valueOf(p.getTwos()));
        Threes.add(String.valueOf(p.getThrees()));
        Fours.add(String.valueOf(p.getFours()));
        Fives.add(String.valueOf(p.getFives()));
        Sixes.add(String.valueOf(p.getSixes()));

        Threeofakind.add(String.valueOf(p.getThreeofakind()));
        Fourofakind.add(String.valueOf(p.getFourofakind()));
        Fullhouse.add(String.valueOf(p.getFullhouse()));
        Smallstraight.add(String.valueOf(p.getSmallstraight()));
        Largestraight.add(String.valueOf(p.getLargestraight()));
        Chance.add(String.valueOf(p.getChance()));
        Yahtzee.add(String.valueOf(p.getYahtzee()));
        Totalscore.add(String.valueOf(p.getTotalscore()));
    }

    boolean checkones = categories.get(0);              //Checkers for which categories are available to score in.
    boolean checktwos = categories.get(1);
    boolean checkthrees = categories.get(2);
    boolean checkfours = categories.get(3);
    boolean checkfives = categories.get(4);
    boolean checksixes = categories.get(5);
    boolean checkthreeofkind = categories.get(6);
    boolean checkfourofkind = categories.get(7);
    boolean checkfullhouse = categories.get(8);
    boolean checksmallstraight = categories.get(9);
    boolean checklargestraight = categories.get(10);
    boolean checkchance = categories.get(11);
    boolean checkyahtzee = categories.get(12);



    System.out.println("| "+                                  "|   | Name            " + stringBuilder(Name));
    System.out.println("|" + isPickable(checkones) +          "|1. | Ones            " + stringBuilder(Ones));
    System.out.println("|" + isPickable(checktwos) +          "|2. | Twos            " + stringBuilder(Twos));
    System.out.println("|" + isPickable(checkthrees) +        "|3. | Threes          " + stringBuilder(Threes));
    System.out.println("|" + isPickable(checkfours) +         "|4. | Fours           " + stringBuilder(Fours));
    System.out.println("|" + isPickable(checkfives) +         "|5. | Fives           " + stringBuilder(Fives));
    System.out.println("|" + isPickable(checksixes) +         "|6. | Sixes           " + stringBuilder(Sixes));
    System.out.println("|" + isPickable(checkthreeofkind) +   "|7. | Three of a kind " + stringBuilder(Threeofakind));
    System.out.println("|" + isPickable(checkfourofkind) +    "|8. | Four of a kind  " + stringBuilder(Fourofakind));
    System.out.println("|" + isPickable(checkfullhouse) +     "|9. | Full House      " + stringBuilder(Fullhouse));
    System.out.println("|" + isPickable(checksmallstraight) + "|1. | Small Straight  " + stringBuilder(Smallstraight));
    System.out.println("|" + isPickable(checklargestraight) + "|11.| Large Straight  " + stringBuilder(Largestraight));
    System.out.println("|" + isPickable(checkchance) +        "|12.| Chance          " + stringBuilder(Chance));
    System.out.println("|" + isPickable(checkyahtzee) +       "|13.| Yahtzee         " + stringBuilder(Yahtzee));
    System.out.println("| "+                                  "|   | Total Score     " + stringBuilder(Totalscore));

}

/*
 * Method for creating the lines for the scoreboard.
 */
public String stringBuilder(List<String> arrIn) {
    StringBuilder sb = new StringBuilder();
    for (String s : arrIn) {
        sb.append("|");
        sb.append(s);
        sb.append(pad(s));
    }
    return sb.toString();
}

/*
 * Method for padding the spaces between columns.
 */
public String pad(String s) {
    int space = 15;
    int sLength = s.length();
    String retPad = "";
    int temp = space - sLength;

    for (int i = 0; i <= temp ; i++) {
        retPad += " ";
    }
    return retPad;
}

public String isPickable(boolean b) {
    if (b == true) {
        return "O";
    }
    else {
        return "X";
    }
}

Gives this print out:

| |   | Name            |one             |two             |three           
|X|1. | Ones            |0               |0               |0               
|X|2. | Twos            |0               |0               |0               
|X|3. | Threes          |0               |0               |0               
|X|4. | Fours           |0               |0               |0               
|X|5. | Fives           |0               |0               |0               
|X|6. | Sixes           |0               |0               |0               
|X|7. | Three of a kind |0               |0               |0               
|X|8. | Four of a kind  |0               |0               |0               
|X|9. | Full House      |0               |0               |0               
|X|1. | Small Straight  |0               |0               |0               
|X|11.| Large Straight  |0               |0               |0               
|X|12.| Chance          |0               |0               |0               
|X|13.| Yahtzee         |0               |0               |0               
| |   | Total Score     |0               |0               |0  

This way looks nice as long as a user doesn't enter a ridiculously long name. This can be fixed by asking the user to enter a shorter name (nick name). Anyway, thanks for your help!


Need Your Help

When Designing a BI Start Schema, Should Dimension Tables Use Only User-Friendly Attribute Values?

sql-server database-design business-intelligence cognos star-schema

I am designing the Dimension tables for my BI Start schema. I have already observed the value of user-friendly attribute values associated with each Dimension value, as these can be used quite rea...

PostSharp remapping obfuscated code

logging msbuild nlog postsharp dotfuscator

I am using NLog to create different loggers with different loglevels foreach class. Each logmessage contains the name of the class and the method.