简体   繁体   中英

Arrays of Unknown Size in Java

I am writing a program in Java to do a number of different mathematical operations and formulas and one of these is matrix addition. I needed a way to make an array of size decided by the user. I could have the user input the dimensions of the array but I wanted a more seamless approach. I decided to have the input the contents of the array by typing the contents separated by commas for different rows and by spaces for different numbers (1 2 3, 4 5 6, 7 8 9 for a 3x3 array) and this is the code i came up with. (sc is the scanner)

String[] pr = sc.nextLine().split(", ");
for(int k = 0; k < pr.length; k++){
    String[] pc = pr[k].split(" ");
    for(int j = 0; j < pc.length; k++){
        pt[k][j] = pc[j];
    }
}

This code does not work; I get a java.lang.NullPointerException if I run it. Initially I was looking for a way to make a 2 dimensional array just by reading one input, something like:

String[][] pt = sc.nextLine().split(", ")(" ");

where it would split with the commas for the different rows and with the spaces for columns within the rows. I don't think anything like this exists in Java, but if it does that would be great. Otherwise, I would appreciate all the help I could get with this. If there is no easy solution to this I might just have to have the user type the array dimensions.

Edit: If this isn't possible then if anyone else has a working method for storing matrices then that would be great.

I assume you don't want to use ArrayList because you'd rather use intrinsics (double) than objects (Double), If that's not the case--just use ArrayList!

If that IS the reason, input into an ArrayList then when it's full, convert that to an array. The ArrayList will do it better than any code you'd probably write and be much more readable.

Although Arrays usually make sense for Intrinsics, 90% of the time I can't figure out peoples fascination with arrays (over ArrayList). Even if you want an array for a specific part of your operation, you are often better keeping it an ArrayList for 90% of the time then converting it to an Array just when you need it.

From question in comments: Array List is simply an array wrapped with some methods and optimized. For instance, you don't ever have to give it a size if you don't want to, you can just use:

ArrayList al=new ArrayList();
al.add(0, "first");
al.add(1, "second");

Internally this will be stored as an array with 2 strings. If you ask for the .size() it will say 2. The actual storage is a bit more optimized than you'd think at first, but you just treat it as an array, for instance in the above you could say:

al.get(1);

and get "second" (They are zero based just like arrays).

As you add more to the ArrayList it will expand it's underlying storage as necessary--you never have to think about it.

ArrayLists can be converted to Arrays at any time if needed.

Here are some "Conversions"

// declare
int[] a;
ArrayList<Integer> al;

// Instantiate
a=new int[6];
al=new ArrayList<>(6); // OR al=new ArrayList<>(); and let it expand itself

// add values
a[0]=5;a[1]=6;
al.add(0,5);al.add(1,6); // Note, if the index is greater 
                         // than the list size, the array 
                         // storage inside the list expands automatically

// Retrieve values
x=a[1];
x=al.get(1);

// Overwrite values
a[0]=9;
al.add(0,9);

// find array size:
len=a.length;
len=al.size();

// Iterate over:
for(int i:a) ...
for(int i:al) ... // Yes, identical

The main advantage is that in eclipse if you type al. you will get a LOT of really useful methods right at your fingertips, but if you type a. you won't get much, you have to look up utility methods in the Arrays class and puzzle your way through things. That and the way ArrayLists manage their own size...

You may want to use Java 8 Streams API to implement such two-dimensional array parsing. The following draft implementation parses a string into a two-dimensional array:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Program {
    public static void main(final String[] args) {
        final String arrayString = "1 2 3, 4 5 6, 7 8 9";
        final List<List<Integer>> array = parseArray(arrayString);
        System.out.println(array);
    }

    private static List<List<Integer>> parseArray(final String arrayString) {
        final List<List<Integer>> rows = Arrays.stream(arrayString.split(","))
            .map(Program::parseRow)
            .collect(Collectors.toList());

        final long distinctColumnSizeCount = rows.stream()
            .map(List::size)
            .distinct()
            .count();
        if (distinctColumnSizeCount > 1) {
            throw new IllegalArgumentException("Some rows have different column count");
        }

        return rows;
    }

    private static List<Integer> parseRow(final String rowString) {
        return Arrays.stream(rowString.trim().split("\\s*"))
            .filter(((Predicate<String>) String::isEmpty).negate())
            .map(Integer::valueOf)
            .collect(Collectors.toList());
    }
}

The appropriate loop (using the Scanner class to read line-by-line) may be used to parse the required number of the two-dimensional arrays.

Hope this helps.

You can of course do this without the need for ArrayList, that is, if you prefer to just stick with filling a simple 2D Array. Quite honestly, I prefer using a List object but never the less it can all be done with a 2D Array. Here's how: (the following examples assumes that your 2D array columns will all be the same):

If you prefer to create your 2D Array as a 2D String Array as per your original question:

String values = "1 2 3, 4 5 6, 7 8 9";
String[] pR = values.split(",");

// Declare and initialize your 2D String Array
String[][] dp = new String[pR.length][pR[0].trim().split("\\s+").length];

// Fill the 2D String Array
for (int i = 0; i < pR.length; i++) {
    String[] pC = pR[i].trim().split("\\s+");
    for (int j = 0; j < pC.length; j++) {
        dp[i][j] = pC[j]; 
    }
}

And to display the contents of your new 2D String Array in Console:

for (int i = 0; i < dp.length; i++) {
            System.out.print("Column Values in Row Index #" + i + " is: --> ");
    for (int j = 0; j < dp[i].length; j++) {
        System.out.print(dp[i][j] + ", ");
    }
    System.out.println("");
}

or simply use: System.out.println(Arrays.deepToString(dp));

If you prefer to have your 2D Array as an Integer 2D Array then you can do this:

String values = "1 2 3, 4 5 6, 7 8 9";
String[] pR = values.split(",");

// Declare and initialize your 2D Integer Array
int[][] dp = new int[pR.length][pR[0].trim().split("\\s+").length];

// Fill the 2D Integer Array
for (int i = 0; i < pR.length; i++) {
    String[] pC = pR[i].trim().split("\\s+");
    for (int j = 0; j < pC.length; j++) {
        dp[i][j] = Integer.parseInt(pC[j]); 
    }
}

Of course you can use the same display code to view the contents of your 2D Integer Array within Console.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM