I have a 2D Arraylist matrix like
ArrayList[][] table = new ArrayList[10][10];
table[0][0] = new ArrayList();
table[0][1].add(10);
table[1][0].add(20);
table[1][1].add(30);
System.out.println("Value="+table[1][0].get()); //error line
The error occurs in the System.out.println line.
how do I print the values of the arraylist matrix??
can anyone suggest me a method??
You seem to think you have a 2-D matrix of numbers, stored as an ArrayList. That is not what you have at all. Instead, you have a 2-D matrix where each element is an ArrayList. That means you really have 3 dimensions represented in your code. I don't think that's what you want. There are several ways you could achieve two dimensions using the constructs you already have (i.e. without going to some external library).
A 2-D array of numbers
The array is an easy to understand construct, so let's start with that.
Number[][] table = new Number[10][10];
table[0][0] = 0;
table[0][1] = 10;
table[1][0] = 20;
table[1][1] = 30;
System.out.println("Value="+table[1][0].get());
This code declares a 2-D array of type Number, then initializes it with 10 rows and 10 columns. It then partially fills in numbers. As long as you access an element that has already been initialized, you'll be ok. Trying to access an element that hasn't yet been initialized (like table[3][4]) would be bad.
Another way to initialize an array
Number[][] table = { { 0, 10 }, { 20, 30 } };
System.out.println("Value=" + table[1][0]);
This is the same thing as before, but initialized all at once. This particular array only has 2 rows and 2 columns.
Nested ArrayLists
If you want to use an ArrayList instead of an array, that's fine. You just need to realize that the ArrayList actually will contain other ArrayLists, each of which will contain Numbers. Like so:
ArrayList<ArrayList<Number>> table = new ArrayList<>();
table.add(new ArrayList<>());
table.add(new ArrayList<>());
table.get(0).add(0);
table.get(0).add(10);
table.get(1).add(20);
table.get(1).add(30);
System.out.println("Value=" + table.get(1).get(0));
In this example, you first declare an ArrayList that contains ArrayLists that contain Numbers, and initialize the outer ArrayList. Then you create some inner ArrayLists, and finally give each of them some Numbers.
Summary
You can use arrays or ArrayLists as you prefer. You just have to initialize them correctly before accessing their elements. How to initialize depends on the data structure you choose.
All the codes
import java.util.ArrayList;
public class TwoD {
public void example1() {
Number[][] table = new Number[10][10];
table[0][0] = 0;
table[0][1] = 10;
table[1][0] = 20;
table[1][1] = 30;
System.out.println("\nExample 1");
System.out.println("Value=" + table[1][0]);
}
public void example2() {
Number[][] table = { { 0, 10 }, { 20, 30 } };
System.out.println("\nExample 2");
System.out.println("Value=" + table[1][0]);
}
public void example3() {
ArrayList<ArrayList<Number>> table = new ArrayList<>();
table.add(new ArrayList<>());
table.add(new ArrayList<>());
table.get(0).add(0);
table.get(0).add(10);
table.get(1).add(20);
table.get(1).add(30);
System.out.println("\nExample 3");
System.out.println("Value=" + table.get(1).get(0));
}
public static void main(String[] args) {
TwoD me = new TwoD();
me.example1();
me.example2();
me.example3();
}
}
THe actual exception is at the lines
table[0][0] = new ArrayList();
table[0][1].add(10);
You are adding element at 0,0 position and trying to add the arraylist element at 0,1.
Hence the nullpointer.
Try
public static void main(String[] args) {
ArrayList[][] table = new ArrayList[10][10];
table[0][0] = new ArrayList();
table[0][0].add(10);
table[0][0].add(20);
table[0][0].add(30);
System.out.println("Value="+table[0][0].get(1));
}
For using ArrayList, you must first declare the type of ArrayList in angular braces. Try using the code snippet as below:
ArrayList<ArrayList<Integer>> table = new ArrayList<ArrayList<Integer>>(); //2d ArrayList
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(10);
x.add(20);
table.add(x);
table.add(x);
System.out.println("Value="+table); //Prints table[][]
System.out.println("Value="+table.get(0)); //Prints table[0]
System.out.println("Value="+table.get(0).get(1)); //Prints table [0][1]
To insert a new row, you must do
table.add(new ArrayList<Integer>());
and to append another element on a specific row you must do
table.get(row).add(someValue);
If you are looking for something more than toy project you should seriously consider using some external matrix library. Arrays will be painful in maintenance.
I could recommend EJML. With usage of this library your code will look like this:
BlockMatrix64F matrix = new BlockMatrix64F(10, 10);
matrix.set(0,1,10);
matrix.set(1,0,20);
matrix.set(1,1,30);
System.out.println("Value="+matrix.get(1,0));
Additionally it is quite likely that you will have to make some calculations inside your matrix. Library will have some support for basic ones, and will save you some time.
Related
What I'm trying to do with this code is that it gives the user a choice between 2 items in a list and the selected item is taken to a new list in the list of lists. I just wanted to know if the implementation of my new list creation is correct or no. I have another non related bug in the program so I can't test if the implementation works or not.
public static void compareTwo(List<List<String>> list){
int result;
for (int j = 0;j<list.size();j++) {
if ((list.get(j).size() / 2) % 2 == 0) {
for (int i = 0; i < list.get(j).size(); i = +2) {
String x = list.get(j).get(i);// gets stuff inside the inner list
String y = list.get(j).get(i+1);
System.out.println("1 ("+x+") or 2 ("+y+")" );
result = Integer.valueOf(scan.nextLine());
list.add(j + 1, new ArrayList<String>() {
});// add another inner list to biglist
list.get(j+1).clear();//clears the new inner list
if (result==1){
String z = list.get(j).get(i);
list.get(j+1).add(z);
}
else{
String z = list.get(j).get(i+1);
list.get(j+1).add(z);
}
}
}
list.add(j + 1, new ArrayList<String>() {
});// add another inner list to biglist
list.get(j+1).clear();//clears the new inner list
This is creating an anonymous subclass of ArrayList: unless you've got a good reason to do that, don't. Also, you don't need to clear a newly-created ArrayList, it's already empty.
As such, you can reduce this code to:
list.add(j + 1, new ArrayList<>());
I can see two serious problems in your code:
Since the following line is trying to access value at index i + 1, the for loop must be for (int i = 0; i < list.get(j).size() - 1; i = +2) to avoid IndexOutOfBoundsException. In your code it is, for (int i = 0; i < list.get(j).size(); i = +2).
String y = list.get(j).get(i+1);
In the following line, you are not handling exceptions for the cases when the user enters a non-integer value.
result = Integer.valueOf(scan.nextLine());
It should be like
boolean valid;
do {
valid = true;
try {
result = Integer.parseInt(scan.nextLine());
} catch (NumberFormatException e) {
System.out.println("This is not an integer. Please try again.");
valid = false;
}
} while (!valid);
Apart from these two serious problems, the second line in the following code snippet doesn't make sense as there is no element to clear in the newly added inner list
list.add(j + 1, new ArrayList<String>() {});// add another inner list to biglist
list.get(j+1).clear();//clears the new inner list
You can use this version for simplicity and readability
List<String> inner = new ArrayList<>();
list.add(j + 1, inner);
, or some java's double-brace initialization
list.add(j + 1, new ArrayList<>(){{
add("hello");
add("world");
}});
Edit: I want this method to sort in ascending order based on any column the user want (each data in the same respective row is 'attached' to each other). There are 4 column in the table. if the user want to sort in based on first column then he should do something like
mySortedTable[][] = ClassName.quickSort(myUnsortedTable,0);
As you can see I tried to code what my title said. For some reason our data table is organized in a 2d Array of Strings(which is NOT handy, had to convert back and forth to implement ArrayList). I used the first data as the pivot. Mind debugging it together with me? :)
public static String[][] quickSort(String[][] data,int column) {
//1st step, create ArrayLists needed and compare the data by the pivot to determine which ArrayList to be filled.
ArrayList<String[]> hiData = new ArrayList<String[]>();
ArrayList<String[]> loData = new ArrayList<String[]>();
ArrayList<String[]> pivots = new ArrayList<String[]>();
String[] pivot = {data[0][0],data[0][1],data[0][2],data[0][3]};
for(String[] row : data) {
if(row[column].compareTo(pivot[column])<0)
loData.add(row);
else if (row[column].compareTo(pivot[column])>0)
hiData.add(row);
else pivots.add(row);
}
//To decide whether is needed to create the array from the ArrayList for recursively sort the parted data.
if(loData.size()>0) {
String[][] loDataArr = new String[loData.size()][4];
for(int i=0;i<loData.size();i++)
loDataArr[i]=loData.get(i);
if(loData.size()>1)
loDataArr = quickSort(loDataArr,column);
}
if(hiData.size()>0) {
String[][] hiDataArr = new String[hiData.size()][4];
for(int i=0;i<hiData.size();i++)
hiDataArr[i]=hiData.get(i);
if(hiData.size()>1)
hiDataArr = quickSort(hiDataArr,column);
}
//Combine parted data into new array and return it to feed the recursive back up until the first recursive call.
String result[][] = new String[hiData.size()+loData.size()+pivots.size()][4];
int j=0;
for(String[] row : loData) {
result[j]=row;
j++;
}
for(String[] row : pivots) {
result[j]=row;
j++;
}
for(String[] row : hiData) {
result[j]=row;
j++;
}
return result;
}
It outputs all the arrays, but is not sorted and also not equals with the arrays it started with. Also side question, I want to ask if ArrayList<String[]> do NOT smells bad, or is it?
In Java, arrays are always one dimensional - although their element type may be an array itself. So a two dimensional array in Java is just an array of arrays.
This fact becomes very handy when you want to sort an array so that rows stick together. You treat each row as an object, and use a comparator to compare the object.
Here is a little demonstration:
public class SortDemonstration {
public static void main(String[] args) {
String[][] table = {
{"The", "Quick", "Brown"},
{"Fox", "Jumped", "Over"},
{"A", "Lazy", "Dog"}
};
Arrays.sort( table, new ColumnComparator(0));
System.out.println( Arrays.deepToString(table));
Arrays.sort( table, new ColumnComparator(1));
System.out.println( Arrays.deepToString(table));
Arrays.sort( table, new ColumnComparator(2));
System.out.println( Arrays.deepToString(table));
}
private static class ColumnComparator implements Comparator<String []>{
private final int index;
public ColumnComparator(int index) {
this.index = index;
}
#Override
public int compare(String[] o1, String[] o2) {
return o1[index].compareTo(o2[index]);
}
}
}
The ColumnComparator class is the key to the solution. It implements a comparator of two string arrays (two rows). It compares the rows based on the item at the index it was instantiated with.
Thus a new ColumnComparator(0) compares two rows based on the first column. A new ColumnComparator(1) compares two rows based on the second column, etc.
Now that you have this comparator class, you can sort an array of "rows" using it. The output from this program is:
[[A, Lazy, Dog], [Fox, Jumped, Over], [The, Quick, Brown]]
[[Fox, Jumped, Over], [A, Lazy, Dog], [The, Quick, Brown]]
[[The, Quick, Brown], [A, Lazy, Dog], [Fox, Jumped, Over]]
I found the problem in my code. I built the parted data using the unsorted ArrayList instead of the sorted 2 dimensional array.
//Second step...
String[][] loDataArr = new String[loData.size()][4];
String[][] hiDataArr = new String[hiData.size()][4];
if(loData.size()>0) {
for(int i=0;i<loData.size();i++)
loDataArr[i]=loData.get(i);
if(loData.size()>1)
loDataArr = quickSort(loDataArr,column);
}
if(hiData.size()>0) {
for(int i=0;i<hiData.size();i++)
hiDataArr[i]=hiData.get(i);
if(hiData.size()>1)
hiDataArr = quickSort(hiDataArr,column);
}
String result[][] = new String[hiData.size()+loData.size()+pivots.size()][4];
int j=0;
for(String[] row : loDataArr) {
result[j]=row;
j++;
}
for(String[] row : pivots) {
result[j]=row;
j++;
}
for(String[] row : hiDataArr) {
result[j]=row;
j++;
}
return result;
}
I was wondering if you could help me with this problem, I'm stuck for a day in trying to solve this one. So basically what I want to do is have a list that will contain an array of an array.
I have this initialization
List<double[][]> points = new ArrayList<double[][]>();
I add the elements this way:
points.add(existing.Foods);
My beeColony class contains the data that I want to add:
public class beeColony{
double Foods[][]=new double[FoodNumber][D];
....
}
And here's how I declare an instance of it:
public beeColony existing=new beeColony();
Here's a snippet of the code:
for(run=0;run<existing.runtime;run++)
{
for (iter=0;iter<existing.maxCycle;iter++)
points.add(existing.Foods);
}
What happens is that when I output all the items the list, it only contains the last added items.
for example:
Foods = {(0,0), (1,1), (2,2), (3,3)}
points.add(Foods);
Foods = {(4,4), (5,5), (6,6), (7,7)}
points.add(Foods);
The way that I understand it is that
points.get(0)[0] should countain 0,0 and so on and points.get(1)[0] should contain 4,4 and so on. But what happens is points.get(0) also has the same values as points.get(1)
Collections like ArrayList<X> contain references to X objects, like one end of a string the other end of which is "tied" to the object itself, i.e., where the data resides.
This is also true for arrays like double[][].
What you do is to copy and store the reference end repeatedly, but at the other end there is one and the same double[][]. You can change the contents of that array, but all stored string ends lead to the same array object.
You must create new copies of that array to hold different array values. If you create another BeeColony, it will have another foods array. Otherwise, use new double[m][n] and copy the values. This is how:
double[][] d = { {1,2}, {3,4}, {5,6} };
// create the vector of (still missing) rows:
double[][] copy = new double[d.length][];
for( int row = 0; row < d.length; ++row ){
// create another row of appropriate length:
copy[row] = new double[d[row].length];
// copy the element values
System.arraycopy( d[row], 0, copy[row], 0, d[row].length );
}
PS: You should stick to Java conventions. Classe names are written in camel case starting with an upper case letter; variables and methods should start with a lower case letter. Loops should declare the loop counter inside the for: for( int run = 0;... ). Avoid public for class fields; code getters and setters to access private class fields.
You could use combination of array and iterator to get the work done,
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class listerr {
static int getrandom(){
Random r = new Random();
int next = r.nextInt(100);
return next;
}
static double[][] getarr(){
double[][] arr = {{getrandom(),getrandom()}, {getrandom(),getrandom()},
{getrandom(),getrandom()}, {getrandom(),getrandom()}};
return arr;
}
public static void main(String[] args) {
List<double[][]> points = new ArrayList<double[][]>();
for(int run=0;run<3;run++)
{
double[][] arr = getarr();
points.add(arr);
}
Iterator itr = points.iterator();
while(itr.hasNext()){
double[][] dbl = (double[][]) itr.next();
for (int i=0;i<4;i++)
{ for (int j=0;j<2;j++){
System.out.println(dbl[i][j]);
}
}
}
}
}
Basically I have two arrays each filled with the same number of values (although the number of values in each array will stay the same, the number of these values can increase or decrease etc.)
The first array list has a list of names e.g.
Sam
Dean
Alice
Jane
Steve
The second array list has a list of index locations which I would like the above items to be stored at with a 3rd list-array e.g.
2nd array index locations.
3
2
5
1
4
I have used arraylists as below:
ArrayList namelist = new ArrayList();
Simply sort the list with names. You can use Collections.sort() because the strings are compareable. Then create the new list an add the string in the order of the indices.
List<String> newList = new ArrayList<>(); // or new ArrayList<String>(); for source level below 1.7
Collections.sort(nameslist);
for(Integer idx : indexList)
{
newList.add(nameslist.get(idx - 1));
}
You have to create a third array with the same size as the other two. Then you have to use the values of intArray as indices for the sortedStrArray like so:
public class JavaApplication
{
// Utilisation
public static void main(String[] args)
{
// The arrays are just here to make the initialization shorter.
// You can initialize strArrayList and
// intArrayList from the beginning with the add method if you want.
String strArray[] = new String[] { "Sam", "Dean", "Alice", "Jane", "Steve" };
Integer intArray[] = new Integer[] { 3, 2, 5, 1, 4 };
// Put array data in ArrayLists
List<String> strArrayList = new ArrayList<String>(Arrays.asList(strArray));
List<Integer> intArrayList = new ArrayList<Integer>(Arrays.asList(intArray));
List<String> sortedList = sortArrayListByIndices(strArrayList, intArrayList);
// Output order should be: Jane, Dean, Sam, Steve, Alice
for(String str : sortedList)
{
System.out.println(str);
}
}
// Implementation
public static List<String> sortArrayListByIndices(List<String> strArrayList,
List<Integer> intArrayList)
{
String sortedStrArray[] = new String[strArrayList.size()];
int i = 0;
for(String str : strArrayList) // Iterator is better style
{
// indices start with 1, array starts with 0
final int index = intArrayList.get(i) - 1;
sortedStrArray[index] = str;
i++;
}
return new ArrayList<String>(Arrays.asList(sortedStrArray));
}
}
The desired algorithm has its own method now and I wrote a little program that utilizes/tests it.
I have two ArrayLists:
Array 01:
ArrayList<String> uniqueFiletypes --> which contains unique filetypes (e.g .zip etc..)
Array 02:
ArrayList<Integer> countFiletypes --> which counts how many of each filetype there is, for example 8 .zip's
And to skip right to the question:
I need to make some kind of "ranking", which means the highest count of filetypes gets the first place, etc...
Another problem: It must be an Object[][] (to support JTable), so it is possible to show the result easily.
Example of output: I have 8 .zips, 5 .java and 2 .docx
Object[][] = {{"1", ".zip", "8"},{"2", ".java", "5"}, {"3", ".docx", "2"}}
Where {PLACE, FILETYPE, COUNT}
I'm assuming the order of the items in both lists matches. I.e. the first item in the uniqueFiletypes list has the number of hits equal to the first number in the countFiletypes list.
I would do the following:
Loop through the lists, adding the entries to a Map.
Sort the list of countFiletypes in descending order.
Pull the file types from the map, adding them in the order they're now in in the ordered list.
Something like the following might do the trick:
public static void main(final String[] args) {
final ArrayList<String> uniqueFileTypes = new ArrayList<String>();
uniqueFileTypes.add(".java");
uniqueFileTypes.add(".zip");
uniqueFileTypes.add(".docx");
final ArrayList<Integer> countFileTypes = new ArrayList<Integer>();
countFileTypes.add(5);
countFileTypes.add(8);
countFileTypes.add(2);
final Map<Integer, String> countedFileTypes = new HashMap<Integer, String>();
for (int i = 0; i< uniqueFileTypes.size(); i++ ) {
countedFileTypes.put(countFileTypes.get(i), uniqueFileTypes.get(i) );
}
Collections.sort(countFileTypes);
Collections.reverse(countFileTypes);
final Object[][] data = new Object[countedFileTypes.size()][3];
for(int i = 0; i<countedFileTypes.size(); i++) {
final Integer count = countFileTypes.get(i);
data[i] = new Object[]{(i+1), countedFileTypes.get(count), count};
System.out.println("{" + (i+1) + "," + countedFileTypes.get(count) + "," + count + "}");
}
}
The main method and the system out aren't really needed, I just used them for testing my solution, which produced this output:
{1,.zip,8}
{2,.java,5}
{3,.docx,2}
Granted, this implies a link between the number of hits and the file type which may not be true. For example, if the docx and the java file format both have 9 hits, this solution wouldn't work.
Is it possible for you to merge the two ArrayLists to a single HashMap<String, Integer>?
This map can hold the entries consisting of the unique filetype (String) and its count (Integer). I suggest this because you have a direct link between a filetype and its count - this "link" can be expressed by a HashMap entry.
The conversion of the HashMap to an Object[][] can be done this way:
for (Map.Entry<?,?> entry : map.entrySet()) {
model.addRow(new Object[] { entry.getKey(), entry.getValue() });
}
With the HashMap sorting gets also easier as you do not need to handle two independent array lists.
First approach: As you will work with JTable, Use TableRowSorter as shown in the demo example of tutorial page
Second approach: Assuming you need it not only for JTable
Object[][] array = {{"1", ".zip", "8"},{"2", ".java", "5"}, {"3", ".docx", "2"}};
List<Object[]>data = Arrays.asList(array);
Comparator<Object[]>comparator = new Comparator<Object[]>() {
#Override
public int compare(Object[] o1, Object[] o2) {
return ((String)o1[2]).compareTo((String)o2[2]);
}
};
Collections.sort(data, Collections.reverseOrder(comparator));
array = (Object[][]) data.toArray();