How to Add elements into ArrayList in non-continuous indexes - java

I'm trying to add elements into Arraylist using non-continuous indexes, for example:
I want to add an element at index 3 first before adding any element at indexes (0,1,2). I will also fill up the indexes at 0,1,2 later.
Here's my code:
public static void main(String[] args) throws FileNotFoundException {
List<Integer> numbers= new ArrayList<Integer>();
Scanner inp = new Scanner(System.in);
int[] x = {1,5,2,4,3,0};
System.out.println("Enter elements:"+"\n");
for(int i=0;i<x.length;i++) {
int index = x[i];
numbers.add(index, inp.nextInt());
}
I seem to get this error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.rangeCheckForAdd(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at Test1.main(Test1.java:28)
I understand the error, but I don't seem to find a way out of this problem. Any help will be much appreciated. If at all there's another fancy data structure which allows me to do non-continuous indexing please let me know, excuse me if my questions doesn't make any sense.

Have you thought about using a Map?
Map<Integer,Integer> myNumbers = new HashMap<>();
myNumbers.put( 4, 100 );
myNumbers.put( 2, 199 );
myNumbers.put( 1, 150 );
System.out.println( myNumbers.get( 2 ) );
There are multiple implementations of Map, e.g. HashMap or TreeMap. Which one to go for, depends on your requirements, for example, if you want to store the elements in a certain order or if you don't care about the order.
In your use case the Map could be used like this:
int[] x = { 1,5,2,4,3,0 };
// Try this instead of the above array, as well:
//int[] x = { 1337, 42, 777 };
// The Map can take an (almost) unlimited number of entries and gaps between
// indices / keys (e.g. 0, 1, 7, 23) are no problem. Only elements that you
// *put* into the Map, are part of it.
Map<Integer,Integer> numbersMap = new TreeMap<>();
System.out.println( "Enter elements:\n" );
try( Scanner inp = new Scanner( System.in ) ) {
for( int i=0; i<x.length; i++ ) {
int index = x[i];
System.out.print( "Enter element " + index + ": " );
int userInput = inp.nextInt();
numbersMap.put( index, userInput );
}
}
System.out.println( "Your Map contains these entries:" );
for( Map.Entry<Integer,Integer> entry : numbersMap.entrySet() ) {
System.out.println( "Element[" + entry.getKey() + "] = " + entry.getValue() );
}
As your indices in the x array are continuos, without gaps, zero-based and known in advance, you could use something like this in this special case, as well:
int[] x = { 1,5,2,4,3,0 };
Integer[] output = new Integer[ x.length ];
System.out.println( "Enter elements:\n" );
try( Scanner inp = new Scanner( System.in ) ) {
for( int i=0; i<x.length; i++ ) {
int index = x[i];
System.out.print( "Enter element " + index + ": " );
int userInput = inp.nextInt();
output[ index ] = userInput;
}
}
List<Integer> numbers = Arrays.asList( output );
System.out.println( numbers );
But I'd prefer the Map approach as it's more flexible and less error-prone.

You have an arraylist, but you seem to forget that you haven't set the initial size of the arraylist. The add method that you use places the value at the given index and then shifts everything over to the right, but in this case, there's no index 1. In order to do so, you should either do
List<Integer> numbers= Arrays.asList(new Integer[10]),
which will make an arrayList with 10 "indexes" which hold a value of null, or
ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));,
which will create anarrayList with 10 "indexes" each of which hold a value of 0. For more information, look at this question which you indirectly ask.
Initial size for the ArrayList

Related

Convert a string into a multidimensional arrays with different lengths

I need to execute by command line a code that will provide a multidimensional array with elements with not necessarily equal lengths.
The execution string is bellow:
start /wait java -jar testMSMWithIndex.jar Foursquare_weather_day_root-type_type 0,1,2-4
I'm considering to pass the parameter 0,1,2-4 and then convert it in a multidimensional array with elements of different lengths in this case, i.e. {{0}, {1}, {2, 4}}.
Note that {{0, null}, {1, null}, {2, 4}} does not work to my problem.
Do you guys know how to develop a method or even get directly as an array from args?
I really appreciate any help you can provide.
It's doubtful that anything already exists to do this for you, so you'll have to parse the string for yourself. Something like this would do it:
public static int[][] parseRaggedArrayFromString(String s)
throws NumberFormatException {
String[] ss = s.split(",");
int[][] result = new int[ss.length][];
for (int i = 0; i < ss.length; ++i) {
if (!ss[i].contains("-")) {
result[i] = new int[1];
result[i][0] = Integer.parseInt(ss[i]);
} else {
String[] range = ss[i].split("-", 2);
int lo = Integer.parseInt(range[0]);
int hi = Integer.parseInt(range[1]);
int size = hi - lo + 1;
result[i] = new int[size > 0 ? size : 1];
int j = 0;
do {
result[i][j] = lo;
++lo;
++j;
} while (lo <= hi);
}
}
return result;
}
It's basically a split on , and -. From there is just handling the data. Comments in the code.
/**
* #author sedj601
*/
public class Main {
public static void main(String[] args) {
String input = "0,1,2-3";
String[] firstArray = input.split(",");//Split on ,.
String[][] outputArray = new String[firstArray.length][];//The array that will be holding the output
//Used to process the firstArray
for (int i = 0; i < firstArray.length; i++) {
if (firstArray[i].length() > 1) {//If the lenght is greater than one. split on -.
String[] secondArray = firstArray[i].split("-");
//Subtract the two numbers and add one to get the lenght of the array that will hold these values
int arrayLength = Integer.parseInt(secondArray[1]) - Integer.parseInt(secondArray[0]) + 1;
String[] tempArray = new String[arrayLength];
int increment = 0;//Keeps up with the tempArray index.
//loop from the first number to the last number inclusively.
for (int t = Integer.parseInt(secondArray[0]); t <= Integer.parseInt(secondArray[1]); t++) {
tempArray[increment++] = Integer.toString(t);//Add the data to the array.
}
outputArray[i] = tempArray;//Add the array to the output array.
} else {//If the lenght is 1, creat an array and add the current data.
String[] tempArray = new String[1];
tempArray[0] = firstArray[i];
outputArray[i] = tempArray;
}
}
//Print the output.
for (String[] x : outputArray) {
for (String y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}
Output:
--- exec-maven-plugin:1.5.0:exec (default-cli) # JavaTestingGround ---
0
1
2 3
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 1.194 s
Finished at: 2021-01-08T00:08:15-06:00
------------------------------------------------------------------------
I really think that's possible when you create an array of type Object .(not a good idea) Since multi-D arrays can only hold arrays of same length (int[][]). Then you create and retrieve values from array by casting...
I am trying here to be creative and adopt to your requirements..
public class x {
public static void main(String[] args) {
Object[] arguments = new Object[args.length];
// Then make a loop to capture arguments in array..
// or add manually
arguments[0] = new String[]{args[0]};
arguments[1] = new String[]{args[1],args[2]};
//Then retrieve info from object later by casting
System.out.println(java.util.Arrays.toString((String[]) arguments[1]));
}
}
...
Although, please consider using a collection...
While I waited for the answer, I found a way to solve the problem.
The relevant information here is that we do not need to set the second array dimension in its instantiation.
The code is below:
// INPUT string = "2-3,1,4-5"
private static String[][] featuresConversion(String string) {
String[] firstLevel = string.split(","); // 1st lvl separator
String[][] features = new String[firstLevel.length][]; // Sets 1st lvl length only
int i = 0;
for (String element : firstLevel) {
features[i++] = element.split("-");
}
return features;
}
I want to thank you all. All suggested solutions also work fine!

NullPointerException from copying a growing inner array and outer array

I have done as much research as I can into similar questions about 2D arrays and NullPointerException (NPE), but have not found an answer that resembles my situation.
My program is supposed to be very basic: take an input "image"-file of integer values, and "soften" those values by taking the average of values around each.
I'm having trouble with the initial process of copying the file into a 2 dimensional array with while loops, though the loops do not seem to be the problem, as I have tried the do-while loop already.
I initially tried using Arrays.copyOf to copy the arrays, but that initially gave me an NPE, so I tried writing my own static methods to do the job, because I read somewhere that Arrays.copyOf only works for one dimensional arrays.
public class ex7_imageSmoother {
public static void main ( String[] args ) throws IOException {
// build utility object(s)
Scanner ScUser = new Scanner( System.in );
// ph for ascii art
System.out.println( "\n\nAre your ready to Soften some \"hard\" files?" );
////..repeat program by prompt
String stRepeat1;
do {
// get hard file name to be softened
System.out.print( "\n\nWhat file would you like to soften? " );
String StHardName = ScUser.nextLine().trim();
File FiHardIn = new File ( StHardName );
Scanner ScHardIn = new Scanner( FiHardIn );
//-- build 2d "Hard" array
// array will be of at least one cell
int[][] AyHardImg = { { 0 } } ;
int iRowCount = 0;
//// for every line in the file; i.e. check that there is a next line
while (ScHardIn.hasNextLine() ) {
// create a string that can be read through by scanner for every line of the file
String StInLine = ScHardIn.nextLine();
// build scanner to read through each row
Scanner ScInLine = new Scanner( StInLine );
// use static method to copy array; make larger on further iterations
AyHardImg = smCopyArrayOuter( AyHardImg, iRowCount );
int iColCount = 0;
//// for every integer in the row
while ( ScInLine.hasNextInt() ) {
// create temporary array in an attempt to circumvent NPE
int[] temp = new int[ AyHardImg[ iRowCount ].length ]; // ...--... this line creates the NPE!!
// copy into temp array all values from inner array of 2d array
for (int i = 0; i < AyHardImg[ iRowCount ].length; i++) {
temp[ i ] = AyHardImg[ iRowCount ][ i ];
}
// copy array and make larger on further iteration
temp = smCopyArrayInner( temp, iColCount );
// use temp array to copy into 2d inner array; included is commented out previous attempt without temp array
AyHardImg[ iRowCount ] = temp; //= smCopyArray( AyHardImg[ iRowCount ], iColCount );
AyHardImg[ iRowCount ][ iColCount ] = ScInLine.nextInt();
iColCount++;
}
iRowCount++;
ScInLine.close();
}
// test algorithm works as intended by printing hard array to screen
for ( int i = 0; i < AyHardImg.length; i++ ) {
for ( int j = 0; j < AyHardImg[i].length; j++ ) {
System.out.print ( AyHardImg[ i ][ j ] + " " );
}
System.out.println();
}
ScHardIn.close();
// get user response to repeat program
System.out.print( "Would you like to soften another file (y/n)? " );
stRepeat1 = ScUser.nextLine().trim().toLowerCase();
} while ( stRepeat1.equals( "y" ) );
}
/*-----
* copies inner array, hopefully to solve null
* pointer exception
*------------------*/
public static int[] smCopyArrayInner( int[] AyX, int growth ) {
int[] AyY = new int[ AyX.length +growth ];
for ( int i = 0; i < AyX.length; i++ ) {
AyY[ i ] = AyX[ i ];
}
return AyY;
}
/*-----
* copies outer array, hopefully to solve null
* pointer exception
*------------------*/
public static int[][] smCopyArrayOuter( int[][] AyX, int growth ) {
int[][] AyY = new int[ AyX.length +growth ][];
for ( int i = 0; i < AyX.length; i++ ) {
AyY[ i ] = AyX[ i ];
}
return AyY;
}
}
NPE is as follows
Exception in thread "main" java.lang.NullPointerException
at ex7_imageSmoother.main(ex7_imageSmoother.java:101)
Thank you to anyone who read this question in an attempt to help but I figured it out by "debugging" the logic manually.
Essentially I wrote a smaller test program that dealt with just a single line of input into a one dimensional array and noticed that my smCopyArrayOuter and smCopyArrayInner were both growing larger than they needed to be.
in essence the line
int[][] AyY = new int[ AyX.length +growth ][];
became
int[][] AyY = new int[ 1 +growth ][];
which solved the problem.
I was also able to do away with the temp array and deal with the AyHardImg directly which you can see if you check out the repo on gitHub which is github.com/q1pt2rx/ex7_imageSmoother.
as of posting this answer the program is incomplete but this NPE issue is resolved.

Add one number from an array to another (by column)

I have been trying to figure out how to add one number in an array to another number in an array. I parsed the numbers in a String into integers, and separated them by columns. Then, I added each column into an array.
What I would like to solve is how to add all the numbers in a column.
The numbers are from a text file.
// numbers.txt:
Bob, 100, 98, 95
Alex, 85, 90, 92
I already used bufferedReader and parsed the numbers, from String to int.
The challenge is adding the numbers by column.
For example, if there are 3 numbers in each array, I just want to add the first numbers in each array.
Q1 is [100, 98, 95]
Q2 is [85, 90, 92]
Only 100 + 85 together.
Below are the codes that I have so far.
Any help on how to proceed will be awesome! Thanks for your time.
int Q1 = Integer.parseInt(columns[1]);
int Q2 = Integer.parseInt(columns[2]);
ArrayList<Integer> Q1list = new ArrayList<>();
Q1list.add(Q1);
Q1list.add(Q2);
double total = 0.0;
for (int i = 0; i < Q1list.size(); i++) {
total += Q1list.get(i);
}
System.out.println(total);
Well, usually when you want to add up the numbers from the array in to a sum you want to iterate over all the indexes in that array. From the loop you've written I cannot see going to all the numbers into the array in any way.
Please revise how for loop is used!
Here is a good explanation, hope it helps
Java: Array with loop
I think you should have at least 2 columns array.
After don't forget your index (in your loop)
Code suiggested:
public static void main(String[] args) {
int [] q1 = { 100 , 98 , 95 };
int [] q2 = { 85 , 90 , 92 };
List<Integer> sumList = new ArrayList<>();
// First solution (what you ask)
sumList.add( q1[0] + q2[0] );
System.out.println("Add Q1[0] + Q2[0]: " + sumList.get(0));
// Second solution (add all)
for( int i = 0 ; i < q1.length ; i++)
{
sumList.add(q1[i] + q2[i]);
}
// Check your result
for( int i : sumList )
System.out.println("Result: " + i);
}
And result gives:
// First solution (what you ask)
Add Q1[0] + Q2[0]: 185
// Second solution (add all)
Result: 185
Result: 185
Result: 188
Result: 187
I find what you want:
// Scanner
StringTokenizer i1 = new StringTokenizer(" [100,98,95]", "[,]");
StringTokenizer i2 = new StringTokenizer(" [85,90,92]", "[,]");
List<Integer> q1List = new ArrayList<>();
List<Integer> q2List = new ArrayList<>();
while( i1.hasMoreTokens() ){
try {
Integer intRes = Integer.parseInt(i1.nextToken());
System.out.println("Test1: " + intRes);
q1List.add(intRes);
}
catch( NumberFormatException e) {}
}
while( i2.hasMoreTokens() ){
try {
Integer intRes = Integer.parseInt(i2.nextToken());
System.out.println("Test2: " + intRes);
q2List.add(intRes);
}
catch( NumberFormatException e) {}
}
// Second solution (add all)
for( int i = 0 ; i < q1List.size() ; i++)
{
sumList.add(q1List.get(i) + q2List.get(i));
}
// Check your result
for( int i : sumList )
System.out.println("Result 2 : " + i);
Sorry for the long time but I have to find on web the answer.
Simples reads file line by line and set new string for each new line...
After that, for each string you can use Strink tokenizer with delimiter in your case : ",".
Take carefull that your first parameter shall be:
null (code for that)
name (catch this string)
other (maybe try catch)
I find this link on stack:
Using Java 8, what is the most preferred and concise way of printing all the lines in a file?
Good luck

Reading from file into Array

I have a file with numbers. It looks as follows:
1 2
3 4
5 6
7 8
9 10
The problem occurs while reading the numbers into Array.
Here is a piece of code:
Scanner file1 = new Scanner( new File("file1.txt") );
int lengt_h = 0;
// Here Eclipse crashes...
while( file1.hasNext() ) lengt_h++;
int[] numberArray = new int[lengt_h];
for(int i=0; i<numberArray.length; i++) {
numberArray[i] = file1.nextInt();
}
for(int n: numberArray) System.out.print(numberArray[n] + " ");
Even if I change a hasNext() function into constant length (e.g 10), then numbers in numberArray Array looks as follows:
1 1 1 2 1 1 5 5 1 3
Why the code does not work properly?
problem with you code is you are not moving the Sacanner pointer in while loop so it were infinite loop.
In your last for loop you are trying to access element from numberArray[n] which is wrong because n itself is a number from your array numberArray.
you can try this :
public static void main(String args[]) throws FileNotFoundException {
Scanner file1 = new Scanner(new File("d:\\data.txt"));
int lengt_h = 0;
while (file1.hasNext()) {
lengt_h++;
file1.next();
}
file1 = new Scanner(new File("d:\\data.txt")); // again put file pointer at beginning
int[] numberArray = new int[lengt_h];
for (int i = 0; i < numberArray.length; i++) {
numberArray[i] = file1.nextInt(); // read integer from file
}
for (int n : numberArray)
System.out.print(n + " ");
}
while( file1.hasNext() ) lengt_h++; // infi loop
hasNext method returns true if and only if this scanner has another token
public boolean hasNext()
You are not reading next token and hence hasNext() will always return true
[EDIT]
If you don't know the size of array in advance, its better to use ArrayList
[1] http://www.tutorialspoint.com/java/util/java_util_arraylist.htm
Check the hasNext method here http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNext%28%29
it says "The scanner does not advance past any input."
So to move it further you should move to next token.
Try this:
List<Integer> numberArray = new ArrayList<Integer>();
while (file1.hasNext())
numberArray.add(file1.nextInt());
for (Integer n : numberArray)
System.out.print(n + " ");

How to find the number of different duplicate values in an array with Java

I have a slight problem with a programme im working on, I need to be able to look through an array in Java and find the number of different duplicates in that array, for example if the array have the values 4, 6, 4 I need to be able to display:
There are:
2 words of length 1 (4 characters)
1 word of length 2 (6 characters)
What I've currently got is -
public class wordLength {
public static void main(String[] args) {
String userInput1 = "Owen Bishop Java ";
String [] inputArray = userInput1.split(" ");
for (int i = 0; i < inputArray.length; i++) {
int length = inputArray[i].length();
int inputArray2 = length;
System.out.println(inputArray2);
}
}
}
This currently will split the string into an array whenever there is a space, and then find and print the length of each of the words in the array, I need to show the amount of words that are the same length.
I'm really new to Java and appreciate this is probably an incredibly easy problem but any help would be hugely appreciated, thanks.
Without writing the whole thing (or making use of 3rd party libraries - I note you're new to Java so let's not complicate things), I would consider the following.
Make use of a Map<Integer,Integer> which would store the number of words of a particular length. e.g. to populate:
Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
for (String word : words) {
Integer current = counts.get(word.length());
if (current == null) {
current = 0;
}
current++;
counts.put(word.length(), current);
}
and then iterate through that to output the number of words per word count. Note that the above makes use of boxing.
The advantage of using a Map is that (unlike your array) you don't need to worry about empty counts (e.g. you won't have an entry if you have no words of length 5). That may/may not be an issue depending on your use case.
You can create an int array of length 20(or the maximum word length in English) and increase the index value before you print that value.
arr[length]++;
public class wordLength {
public static void main(String[] args) {
String userInput1 = "Owen Bishop Java ";
String [] inputArray = userInput1.split(" ");
Map<Integer,Integer> wordLengths = new HashMap<Integer,Integer>();
for (int i = 0; i < inputArray.length; i++) {
int length = inputArray[i].length();
if (wordLengths.containsKey(length))
wordLengths.put(length, wordLengths.get(length) + 1);
else
wordLengths.put(length, 1);
}
for (Integer length : new TreeSet<Integer>(wordLengths.keySet()))
System.out.println("Length: " + length + " Count: " + wordLengths.get(length));
}
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class wordLength {
public static void main(String[] args) {
String userInput1 = "Owen Bishop Java ";
String [] inputArray = userInput1.split(" ");
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for (int i = 0; i < inputArray.length; i++) {
int length = inputArray[i].length();
if(map.get(length)==null){
map.put(length, 1);
}
else map.put(length, map.get(length)+1);
}
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println("words of length " +pairs.getKey() + " are " + pairs.getValue());
}
}
}
The output will be:
words of length 4 are 2
words of length 6 are 1
The beginning of your code looks good. What you basically want to keep track of (in my understanding) is a mapping from String length to the number of times this occurred.
public class wordLength {
public static void main(String[] args) {
String userInput1 = "Owen Bishop Java ";
String [] inputArray = userInput1.split(" ");
Map<Integer, Integer> counter = new HashMap<>(); //please note that I use the 'diamond' notation here, this is for Java 1.7 and higher.
for (int i = 0; i < inputArray.length; i++) {
int length = inputArray[i].length();
Integer num = counter.get(length);
if (num == null) {
num = 1;
}
else {
num++;
}
counter.put(length, num);
//or counter.put(length, num == null ? 1 : num++); instead of the if-else
}
//print the results
for (Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("There are " + entry.getValue() + " words with length " + entry.getKey() + ".");
}
}
}
The previous submitted method of arr[length]++; does work, but uses way to many space. Say you have only words of length 20 and beyond, then the first 20 elements of this arr are useless...
Please also note that you can use the map.entrySet() method from the Map interface. It is a better coding practice to use this method than using map.keySet() and after that looking up the associated value. This saves you much look up time. (especially with large user inputs!!!)
I have 2 solutions for above problem
Using extra space i.e. Map to store unique value. Complexity O(n) + Space(N) [N= #unique value]
No extra space. Sorts the input and counts values. Complexity nLog(n) + n
First Solution
Create a map to store each unique value as key and its count as value
Iterate over input array
If value exists as key then increment counter
ELSE if value does exist in map, then put value and set counter as 1
private static void UniqueValueUsingMap(int[] a){
//Map with
// key: unique values
// Value: count as each value (key)
Map<Integer, Integer> store = new HashMap<Integer, Integer>();
for (int i : a) {
Integer key = Integer.valueOf(i);
Integer count = null;
if(store.containsKey(key)){
count = store.get(key);
}else{
count = 0;
}
count++;
store.put(key, count);
}
}
Second solution
Sort the given Array nlog(n). All same values will be together after sort.
Iterate over sorted array
Maintain 2 variable i.e. previous value and counter for current value
When value change, print the value/count and reset the counter
Note: : int defaults to 0 inital value. Need to add additional check for it.
private static void CountValueUsingSort(int[] a){
//Sort the input array
Arrays.sort(a);
int currentValue = 0;
int counter =0;
for (int curr : a) {
if(curr != currentValue){
System.out.println("Value: " + currentValue + " Count:" + counter);
//Reset counter
counter = 0;
}
currentValue = curr;
//increment Count
counter++;
}
}

Categories

Resources