First Element in TwoDimensional Array goes to null? - java

I am using this code to insert the details in to TwoDimensional Array. But while retrieving the data from the array the first element value changes to null.
Cursor consultancy = db.getConsultancy(this);
if(consultancy!=null)
{
consultancy.moveToFirst();
consultancy.moveToNext();
consultancynames = new String[(int) db.getConsultancyCount()-1];
for(int i=0;i<db.getConsultancyCount()-1;i++)
{
consultancynames[i] = consultancy.getString(2);
int consultantid = Integer.parseInt(consultancy.getString(consultancy.getColumnIndex(TimeAndExpensesLocalDB.CT_CONSULTANCYID)));
Cursor project_namecur = db.getProjectCode(this, consultantid);
if(project_namecur!=null)
{
project_namecur.moveToFirst();
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
for(int j=0;j<project_namecur.getCount();j++)
{
projectname[i][j] = project_namecur.getString(3);
project_namecur.moveToNext();
}
}
consultancy.moveToNext();
}
}
//... Print array
for (int i =0; i < consultancynames.length; i++) {
for (int j = 0; j < projectname.length; j++) {
System.out.print(" " + projectname[i][j]);
}
System.out.println("");
}
Output
05-25 12:58:22.700: I/System.out(2373): null null null
05-25 12:58:22.700: I/System.out(2373): Other-1 Other-2 Other-3
I am not sure what is happening.
Thanks for your help guys..

You're creating a new array on each iteration of the loop:
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
So on the first iteration you're creating an array and filling in the first "row" of the array. On the second iteration you're creating a new array (which will default to having null elements) and filling in the second row.
I suspect you need to allocate the "outer" array once before the loop, then allocate the "inner" array based on how many project names there are for that consultant:
// Note: more idiomatic names would be consultancyNames and
// projectNames. It's also unclear why you're subtracting one from the count...
consultancynames = new String[(int) db.getConsultancyCount() - 1];
projectnames = new String[consultancynames.length][];
for (int i = 0;i< consultancenames.length; i++) {
...
projectnames[i] = new String[project_namecur.getCount())];
...
}
Then you'll need to change your display code too, e.g. to
for (int i =0; i < projectname.length; i++) {
for (int j = 0; j < projectname[i].length; j++) {
System.out.print(" " + projectname[i][j]);
}
System.out.println("");
}

Note that you can't do the following:
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
for(int j=0;j<project_namecur.getCount();j++)
{
projectname[i][j] = project_namecur.getString(3);
project_namecur.moveToNext();
}
Here's why:
After the first line projectname will be an array of arrays.
Since the arrays are object references you have an array of object references.
Since the default value of an object reference is null, you'll have an array of null elements.
This means you can't do
projectname[i][j] = project_namecur.getString(3);
since it corresponds to
String[] row = projectname[i];
// row == null !
row[j] = project_namecur.getString(3);

Related

Remove items from custom arraylist implemetation without .remove

I'm working on a custom ArrayList implementation and I have one method where I'm trying to remove an item per conditions from an array such as E[] elements. The array is initialized by doing something like this:
String[] contents = {"chicken", "hippo", "goat"};
ArrayI<String> newarray = new ArrayI(contents);
newarray.chooser(new LongChooser());
It should remove words length 4 or less and return an array like this:
["chicken", "hippo"]
I'm trying not to use any built in methods, like remove(), clone(), arraycopy(), etc. I can't seem to get this to work, I've tried creating a duplicate array and trying to copy elements over like this:
E[] copy = (E[]) (new Object[this.size-1]);
for (int i = 0; i < size; i++) {
if (shorter) {
copy[i] = elements[i];
}
else {
for (int j = i; j<this.size-1; j++) {
elements[j] = elements[j+1];
}
elements[size-1] = null;
size -= 1;
}
for (int i =0; i< copy.length; i++) {
elements[i] = copy[i];
}
size -= 1;
I know this is not the correct way because they aren't the same size array and just returns [longword, longerword, null]. Also I'm pretty sure I should be using the size variable, but it doesn't seem to do much.
How do I get this to work? Thanks.
Create an array to hold the [filtered] results. Its initial size is zero.
Iterate through contents.
If the current element of contents needs to be retained, then
create a temporary array whose length is one greater than the array that holds the results.
copy the results array to the temporary array
set the last element of the temporary array to the current element of contents
assign the temporary array to the results array
Here is the code, using only simple arrays. I presume you can adapt it to your needs. Note that the last line is simply to check the value of newContents. It is not required.
String[] contents = {"chicken", "hippo", "goat"};
String[] newContents = new String[0];
for (String str : contents) {
if (str.length() > 4) {
String[] temp = new String[newContents.length + 1];
for (int i = 0; i < newContents.length; i++) {
temp[i] = newContents[i];
}
temp[newContents.length] = str;
newContents = temp;
}
}
System.out.println(Arrays.toString(newContents));

How to store data in a string array using java collection

I have stored data in a List<String[]> and need to store those data into an another String array using a loop. I have created a String array (value) and stored data in there but the issue is first element is getting replaced by second inside the loop and it will show only the last element at the end of the loop.
CSVReader reader = new CSVReader(new FileReader(csvfile));
List<String[]> data = reader.readAll();
String[] values = new String[5];
for (int i = 1; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here
}
System.out.println(values[1]); // this will show only the last stored value
Lists are 0 indexed so unless you intentionally want to skip the first element then don't start the loop iteration at 1 rather at 0.
Yes, when performing the last println after the loop only data related to the last String[] is shown because at each iteration you're updating values i.e. values = data.get(i); to store the current String[] hence the aforementioned outcome.
You probably want a String[][] as opposed to String[] because each String[] represents a line of the file.
Thus, assuming you only want to get the first five lines from data you can do it as:
String[][] lines = data.subList(0, 5).toArray(String[][]::new);
or for all the lines read:
String[][] lines = reader.readAll().toArray(String[][]::new);
and you can test it with:
System.out.println(Arrays.deepToString(lines));
// generating data
List<String[]> data =
Stream.iterate(0, n -> n + 1)
.limit(10)
.map(i -> new String[]{"a" + i, "b" + i, "c" + i, "d" + i, "e" + i, "f" + i})
.collect(Collectors.toList());
String[][] values = new String[data.size()][];
// copy the data
for (int i = 0; i < data.size(); i++)
{
values[i] = data.get(i).clone();
}
//print the result
Arrays.stream(values).map(Arrays::toString).forEach(System.out::println);
Replace :
for (int i = 1; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here}
With:
for (int i = 0; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here}
I think you have a little error inside the for loop. Try this:
CSVReader reader = new CSVReader(new FileReader(csvfile));
List<String[]> data = reader.readAll();
String[] values = new String[5];
for (int i = 1; i < 5; i++) {
values[i] = data.get(i);
System.out.println(values[1]); // data is getting replaced here
}
System.out.println(values[1]); // this will show only the last stored value
I think you are missing the "[i]" at the first line inside the for loop.
Your data variable contains a list of String[] (string arrays). Your for loop is attempting to store them in values which is a single String[].
Depending on what you are trying to do, you can do as the comments suggest and make a 2D String array. However, the fact that you want to remove them from a perfectly good list of String[]'s leads me to believe you probably want them in one big String[].
Below is an example of how to put the first N (in this case 5) words you parse from the csv into the values variable. However, we would be able to give you better guidance if you provided what the ultimate use case of your code snippet is.
// initialize test data
List<String[]> data = new ArrayList<String[]>();
String[] a = {"a1", "a2"};
String[] b = {"b1", "b2"};
String[] c = {"c1", "c2"};
data.add(a);
data.add(b);
data.add(c);
// big N is how many words you want
int N = 5;
// little n tracks how many words have been collected
int n = 0;
String[] values = new String[N];
// loop through csv collect
for (int i = 0; i < data.size(); i++){
String[] cur = data.get(i);
// loop through the strings in each list entry
for (int j = 0; j < cur.length; j++){
// store value and increment counter
values[n] = cur[j];
n++;
// stop if maximum words have been reached
if (n >= N)
break;
}
// stop if maximum words have been reached
if (n >= N)
break;
}
for (int i = 0; i < values.length; i++)
System.out.println(values[i]);

How to remove and replace an item in an array list in Java?

I have the following code in java,
import java.util.ArrayList;
import java.util.Objects;
public class Cars {
private static ArrayList<String> replaceDuplicates(ArrayList<String> aList) {
for (int i = 0; i < aList.size(); i++) {
for (int j = i + 1; j < aList.size(); j++) {
if (Objects.equals(aList.get(i), aList.get(j))) {
aList.remove(i);
aList.add(i, "");
aList.remove(j);
aList.add(j, "");
}
}
}
return aList;
}
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<>();
cars.add("Ford");
cars.add("Ford");
cars.add("Hyundai");
cars.add("Toyota");
cars.add("Toyota");
cars.add("Toyota");
cars.add("Ford");
cars.add("Honda");
cars.add("GMC");
System.out.println(cars);
cars = replaceDuplicates(cars);
System.out.println(cars);
}
}
The output of this code is - [, , Hyundai, , , Toyota, Ford, Honda, GMC]
I want to replace the name of cars that appear more than once in the array list with a " ". For some reason, in my code if a car's name has appeared thrice in the array list, then the third occurrence isn't getting replaced by " ".
My desired output should be like this - [, , Hyundai, , , , , Honda, GMC]
What am I doing wrong here?
Thank you in advance!
First off: you can simplify this code by using List.set instead of inserting and removing elements.
aList.remove(i);
aList.add(i, "");
would simply become
aList.set(i, "");
You're deleting both entries, if they're duplicate. This leads to the behavior of always deleting an even number of entries. For example:
a b a a c a d a
b a c a d a #first pair removed
b c d a #second pair removed
If the number of elements is odd, there will always remain one element in the list.
Obviously you need some way to remember what elements to delete. A simple approach to this would be to use a flag to remember whether a duplicate of an element has been encountered:
for (int i = 0; i < aList.size(); i++) {
//the flag
boolean duplicate = false;
for (int j = i + 1; j < aList.size(); j++) {
if (Objects.equals(aList.get(i), aList.get(j))) {
aList.set(j, ""); //remove all duplicates with an index higher than i
duplicate = true; //remember that element at index i is a duplicate
}
}
//remove last duplicate element
if(duplicate)
aList.set(i, "");
}
If you still want to use your approach, you can create references to your items before modifying list:
for (int i = 0; i < aList.size(); i++) {
String a = aList.get(i);
for (int j = i + 1; j < aList.size(); j++) {
String b = aList.get(j);
if (Objects.equals(a, b)) {
aList.remove(i);
aList.add(i, "");
aList.remove(j);
aList.add(j, "");
}
}
}

Remove null elements from String array where "All elements are null"

I am tasked with fixing a problem where this code returns string values but because the iterations add null elements it needs to trim or remove those. During debug the value of the array contains mostly "All elements are null", but other solutions like data.removeAll(Collections.singleton(null)); do not work because it is the elements that are null and it still returns as the original size. Is there a way to remove these elements after the iterations of the initial loop or should this be done inside the loop where data is assigned the "value"?
Code:
private String[][] getStringsFromSpreadSheet(Sheet ws) {
int rowNum = ws.getLastRowNum() + 1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[(rowNum - 1)][colNum];
int k = 0;
for (int i = 1; i < rowNum; i++) {
ws.getRow(i);
if (ws.getRow(i) != null) {
for (int j = 0; j < colNum; j++) {
if (ws.getRow(i).getCell(j) != null) {
String value = ws.getRow(i).getCell(j).toString();
if (!value.toString().isEmpty()) {
data[k][j] = value;
}
}
}
}
k++;
}
return data;
}
You can easily trim out null values from a List, but you've been trying to convert your array to a List incorrectly.
Since you've got a two-dimensional array, you need to create a nested list (List<List<String>>) to store the data.
For instance, let's start with a mostly empty String[][]:
String[][] data = new String[3][3];
data[0][0] = "foo";
data[1][1] = "bar";
//data is a 3x3 array
for (int i=0; i<data.length; i++) {
System.out.println(Arrays.toString(data[i]));
}
//[foo, null, null]
//[null, bar, null]
//[null, null, null]
We can take each sub-array, convert it to a list, trim it, and then add the non-empty lists to an enclosing list, like so:
List<List<String>> dataList = new ArrayList<>();
for (int i=0; i<data.length; i++) {
List<String> temp = new ArrayList<>();
Collections.addAll(temp, data[i]);
temp.removeAll(Collections.singleton(null));
if (!temp.isEmpty()) {
dataList.add(temp);
}
}
We can then convert the list back to a String[][], which will be "trimmed" of null data, like so:
String[][] newData = new String[dataList.size()][];
for (int i=0; i<dataList.size(); i++) {
List<String> subList = dataList.get(i);
newData[i] = subList.toArray(new String[subList.size()]);
}
//newData is a 2x1 array
for (int i=0; i<newData.length; i++) {
System.out.println(Arrays.toString(newData[i]));
}
//[foo]
//[bar]
All you need to do is set it to blank string. check the else clause.
private String[][] getStringsFromSpreadSheet(Sheet ws) {
int rowNum = ws.getLastRowNum() + 1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[(rowNum - 1)][colNum];
int k = 0;
for (int i = 1; i < rowNum; i++) {
ws.getRow(i);
if (ws.getRow(i) != null) {
for (int j = 0; j < colNum; j++) {
if (ws.getRow(i).getCell(j) != null) {
String value = ws.getRow(i).getCell(j).toString();
if (!value.toString().isEmpty()) {
data[k][j] = value;
}
} else {
data[k][j] = "";
}
}
}
k++;
}
return data;
Now the data would not have any null values but it may have blank / empty strings.
Based on your comments it seems that you have to return a String[][] for getStringsFromSpreadSheet. Is this correct? If so there is not a nice way to keep track of how many cells are null/not null. 2D arrays have to be rectangular. So if one of your rows has 3 columns populated and one row only has 1 column populated, the array has to be at least 3 columns wide. I have tried to represent this visually below.
Row | Column 1 | Column 2 | Column 3 |
1 | something | something | something |
2 | something | null | null |
So for the above data you have to declare a 2D array at least 2x3 to fit all of your data. No matter what, if one of your rows does not populate all 3 columns, you will always have a null cell for that row. Array.length will always return the size of the array, never the count of how many are null/not null.
Your options are limited if you can only return a String[][]. If you are able to return something else, we can work through some options.

Iterating through all slots that are not null, 2d array?

I must work with a 2d array. The maximum length of the row slots in the array is 100. More often than not, anywhere from 5-20 of these array slots will be filled and not more, however, I must build my code to a max of 100 rows. My question is, is there a way to iterate through only the array slots that have been set, stopping before the last unset, null slots?
//initialize array
String[][] variables = new String[numVariables][100];
//System.out.printf("%s \n", numVariables);
for(int i=0; i < numVariables; i++){
//reads in variable line
String variableLine = fin.nextLine();
//turn variable line into array
varArray = variableLine.split(" ");
numRules = Integer.parseInt(varArray[0].replaceAll("\\s",""));
for(int j=0; j < numRules+1; j++){
variables[i][j] = varArray[j+1];
System.out.printf("%s ", variables[i][j]);
}
System.out.println("\n");
}
//**LATER IN MY CODE ****//
//ITERATE THROUGH 'variables' array and PRINT OUT ONLY VALUES THAT ARE SET
If you populate the array in order from 0 to 100. If the first 51 elements are populated with the string then you could use:
for(int i=0; i < numVariables; i++){
for(int j=0; j < numRules+1; j++){
if (variables[i][j] == null)
break;
System.out.printf("%s ", variables[i][j]);
}
}
Why do you even store the nulls if you don't need them? A String[][] is an array of arrays of String - those inner arrays need not have the same length. You could therefore create each inner array with the number of elements it needs:
//initialize array
String[][] variables = new String[numVariables][];
//System.out.printf("%s \n", numVariables);
for(int i=0; i < numVariables; i++){
//reads in variable line
String variableLine = fin.nextLine();
//turn variable line into array
varArray = variableLine.split(" ");
numRules = Integer.parseInt(varArray[0].replaceAll("\\s",""));
variables[i] = Arrays.copyOfRange(varArray, 1, numRules - 1);
}
and then iterate:
for (String[] var : variables) {
for (String s : var) {
System.out.print(s);
}
System.out.println();
}
You can either use an array of List<String> or you can also keep track of the length of all your rows.
int [] rowLength = new int[numVariables]
for(int i=0; i < numVariables; i++){
/* ... */
numRules = Integer.parseInt(varArray[0].replaceAll("\\s",""));
// store the number of slots in variable[i]
rowLength[i] = numRules+1;
/* ... */
}
Then you iterate only from zero to the length of your row (rowLength[i]).
A third approach (and the one I would prefer) is to not specify the length of the row slots in your array :
String [][] variables = new String[numVariables][];
Then after having calculated numRules:
variables[i] = new String[numRules+1];
Given the situation you have described you'd probably be better off using another data structure, but seeing as you cannot you could keep a record of what values have been changed.
So you could keep an array of the length of each row and end each search there for the row.
String[][] variables = new String[numVariables][100];
int rowLength[] = new int[numVariables];
//...
// get and record the rowLength
//...
for(int x=0; x < numVariables; x ++) {
for(int y=0; y < rowLength[x]; y ++) {
// do your stuff
}
}
}
Or you could use a map or ArrayList to keep track of each of the positions that contain numbers.

Categories