Java not recognizing elements in ArrayList? - java

I have a program where I make an arraylist to hold some cab objects. I keep getting an error that what I get from the message is that java does not recognize that the arraylist has objects in it. This is the error that I am getting.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 20, Size: 20
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at edu.Tridenttech.MartiC.app.CabOrginazer.main(CabOrginazer.java:48)
This is the code that i am trying to get to work
public class CabOrginazer {
private static List<CabProperties> cabs = new ArrayList<CabProperties>();
private static int count = 0;
private static boolean found = false;
public void cabOrginazer()
{
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CabRecordReaper reaper = new CabRecordReaper("C:/CabRecords/September.txt");
CabProperties cabNum;
for(int i = 0; i < 20; i++)
{
cabNum = new CabProperties();
cabs.add(cabNum);
}
while(reaper.hasMoreRecords())
{
CabRecord file = reaper.getNextRecord();
for(int j = 0; j < cabs.size(); j++)
{
if(cabs.get(j).getCabID() == file.getCabId())
{
found = true;
cabs.get(j).setTypeAndValue(file.getType(), file.getValue(), file.getPerGallonCost());
cabs.get(j).setDate(file.getDateString());
break;
}
}
if(found == false)
{
cabs.get(count).setCabId(file.getCabId());
count++;
}
/*for(CabProperties taxi : cabs)
{
if(taxi.getCabID() == file.getCabId())
{
found = true;
taxi.setTypeAndValue(file.getType(), file.getValue(), file.getPerGallonCost());
taxi.setDate(file.getDateString());
break;
}
}*/
}
for(CabProperties taxi : cabs)
{
System.out.print("cab ID: " + taxi.getCabID());
System.out.print("\tGross earning: " + taxi.getGrossEarn());
System.out.print("\tTotal Gas Cost: " + taxi.getGasCost());
System.out.print("\tTotal Service Cost: " + taxi.getServiceCost());
System.out.println();
}
}
}
line 48 is the inside of that if statement where it says cabs.get(count).setCabId(file.getCabId());
with the little knowledge I have of Java. Java should know that there are elements inside of cabs and I should be able to set that id of the cab. What can cause Java not to recognize that the arraylist is populated?

The list isn't populated with an element at item count. Look at the exception: you've got 20 elements in the list, so the valid indexes are 0 to 19 inclusive. You're asking for record 20 (i.e. the 21st record). That doesn't exist.
It sounds like your block should be something like:
if (!found)
{
CabProperties properties = new CabProperties();
properties.setCabId(file.getCabId());
// Probably set more stuff
cabs.add(properties);
}
You may well be able to get rid of the count variable entirely - and your initial population of the list with dummy properties. It's very odd to populate a list like that to start with - that's typically something you do with an array which has a fixed size. One of the main benefits of using a List such as ArrayList is that it's dynamically sized.

Java is recognizing the members just fine. You have 20 members in the array, indexed from index 0 through index 19.
You are asking for index 20, which does not exist.
The loop for:
while(reaper.hasMoreRecords())
must be running many more times than you expect, and your data is hitting the found == false if condition (which you can just say if (!found) { ... ) many times, and on the 21st time it fails with the index-out-of-bounds exception.
You should figure out how to use your debugger too.

Related

CodeHS Billboard Class AP CS A

I am struggling with the CodeHS Java problem Billboard Top 10. I am trying to reference a Musician object within the top10 ArrayList, but I keep getting the error:
non-static variable top10 cannot be referenced from a static context.
Here is the code I have for this segment:
public void add(Musician m) {
//if less than 10 musicians on the list and musician has platinum status, add musician to top10 array list
if(m.getIsPlatinum(m.getAlbumsSold())&&top10.size()<10) {
top10.add(m);
}
//if already 10 musicians (and platinum), call replace method
else if(m.getIsPlatinum(m.getAlbumsSold())&&top10.size()==10) {
replace(m);
}
// else print musician couldn't be added to top10 list
else System.out.println("The musician could not be added to the top10 list.");
}
public static void replace(Musician replacer) {
//if lowest # weeks on top40 is lower than # weeks of new musician: replace old
Musician temp = top10.get(0);
int lowest40Weeks = temp.getWeeksInTop40();
int lowestIndex = 0;
for(int i = 0; i<top10.size(); i++) {
temp = top10.get(i);
if(temp.getWeeksInTop40()<lowest40Weeks) {
lowest40Weeks = temp.getWeeksInTop40();
lowestIndex = i;
}
}
if(lowest40weeks<replacer.getWeeksInTop40()) {
top10.set(lowestIndex, replacer);
System.out.println(replacer.getName() + " has replaced " + top10.get(lowestIndex).getName() + " on the top 10 list.");
}
//print message to user about replacement
//else print musician can't be added because not enough weeks on top40
else {
System.out.println(replacer.getName() + " could not be added to the top 10 list because they do not have enough weeks in the top 40.");
}
}
All of my issues are in the replace method when I reference top10 in a method.
Any help would be appreciated!
Why is Replace static in the first place?
You can't reference a variable that isn't static in a function that is. So just make the replace function not static.

Update Inventory system file with sales values in Java

I am struggling to get my code in Java to do the following:
Inventory Update program.
The first set of records is the master file which reflects an item inventory at the start of the business day. Each master file record contains a part number and a corresponding item stock quantity. Let us assume that the master file contains no more than 5 records.
The second set of records reflects the transactions for each of various items during that day. Transaction records contain have the same format as the master file records: they contain the item number and the corresponding total number of items sold that day. There is unknown number of such transaction records in the input file.
Write a program to update the master file against the transaction file to produce the new master file at the end of the day. A record notice should accompany any item number for which fewer than 10 items remain in the stock.
The actual files look like this. (Master.txt)
444 40
111 30
222 15
134 20
353 5
And the second looks like this (Sales.txt)
134 03
111 29
353 02
222 10
And the updated version of Master.txt should look like this.
444 40
111 1 reorder
222 5 reorder
134 17
353 3 reorder
Here is my code.
import java.io.*;
import java.util.*;
public class inventoryUpdate {
//Exception included due to mOrganize, sOrganize, and PrintWriter
public static void main(String[] args) throws Exception {
Scanner inKey = new Scanner(System.in);
//Preparing the document based on how many item types were sold.
System.out.println("How many types of products were sold?");
int sold = inKey.nextInt();
int[][] inMaster = fileCheck(mOrganize(), sOrganize(sold), sold);
PrintWriter printFile = new PrintWriter("Master.txt");
printFile.println("Item No. \tQuantity");
for (int i = 0; i<5;i++){
if (inMaster[i][1] < 10){
printFile.printf("%-5s %17s You are low in inventory on this item. Please order more.\n", inMaster[i][0], inMaster[i][1]);
}
else{
printFile.printf("%-5s %17s\n", inMaster[i][0], inMaster[i][1]);
}
}
printFile.close();
System.out.println(Arrays.deepToString(inMaster));
}
private static int[][] mOrganize() throws Exception {
File fileRip = new File("Master.txt");
Scanner masterRead = new Scanner(fileRip);
masterRead.nextLine();
int[][] masterData = new int [5][2];
for (int i = 0; i < 5; i++){
for (int i2 = 0; i2 < 2; i2++){
masterData[i][i2] = masterRead.nextInt();
if (masterData[i][i2] < 10){
masterRead.nextLine();
}
}
}
masterRead.close();
return masterData;
}
private static int[][] sOrganize(int sold) throws Exception{
File fileRip = new File ("Sales.txt");
Scanner saleRead = new Scanner(fileRip);
saleRead.nextLine();
int [][] salesData = new int [sold][2];
for (int i = 0; i < sold; i++){
for (int i2 = 0; i2 < 2; i2++){
salesData[i][i2] = saleRead.nextInt();
}
}
saleRead.close();
return salesData;
}
private static int[][] fileCheck(int[][] master, int[][] sales, int sold){
int columnBase = 0;
for(int i = 0; i < 5; i++){
for(int i2 = 0; i2 < sold; i2++){
if (master[i][columnBase] == sales[i2][columnBase]){
master[i][columnBase + 1] -= sales[i2][columnBase + 1];
}
}
}
return master;
}
}
My output is as follows.
How many types of products were sold?
4
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at inventoryUpdate.mOrganize(inventoryUpdate.java:39)
at inventoryUpdate.main(inventoryUpdate.java:14)
The code appears to break at line 14 and is related to my inMaster array.
int[][] inMaster = fileCheck(mOrganize(), sOrganize(sold), sold);
I am sure I am overlooking a syntax error of sorts, but I am failing to wrap my brain around it.
I would appreciate any help possible.
Your problem is probably a lack of making your methods too specific, and you expect too much precision in the input.
In mOrganize, you are explicitly reading away the new lines. However, the last line doesn't contain any newline, so it fails.
To be perfectly honest, nextInt happily skips whitespace, so none of the nextLine statements are necessary at all and your code runs if you remove them.
mOrganize should just be called organize if you follow Java naming conventions, and just readInventory with a File parameter if you want to let it make any sense.
I'm not sure how much you've learned about programming, but things like 5 and 10 in mOrganize are called magic values and should be avoided. What you really want is to create a class e.g. ItemInventory and ItemSales, make a Java List out of those and then read the files until the end. That way your code will work even if there are more or fewer lines in the files.
Here is a bit more advanced example that uses a Map rather than a List:
private static Map<Integer, Integer> readInventory(File file) throws IOException {
var inventory = new HashMap<Integer, Integer>();
try (var lineScanner = new Scanner(file)) {
while (lineScanner.hasNextLine()) {
// we assume each item is on it's own line
var line = lineScanner.nextLine();
try (var itemScanner = new Scanner(line)) {
var no = itemScanner.nextInt();
var amount = itemScanner.nextInt();
if (inventory.put(no, amount) != null) {
// a more specific exception such as InventoryException might be better
throw new RuntimeException("Duplicate item in inventory file");
}
}
}
}
return inventory;
}
an item number is unique after all, and you would not expect it twice in the same inventory.
As you can see, it would be easy to put more information in the same line now, although that would mean changing the return value to something other than Map<Integer, Integer> - for instance Map<Item, Integer> if you define a new Item class.
It is now completely independent of the amount of items in the file, no magic numbers anymore. It also is able to read from any file, rather than just Master.txt.
I hope it is abundantly obvious that rewriting "Master.txt" won't help you with debugging, as you need to restore it each time you run the code.

Test a jump with ASM in Java

I'm trying to prevent conditionals jumps from being useless for example by deleting that :
if(1 > 10) {
return;
}
So I decided to create a BasicInterpreter to check if the frame of the jump is null and if so remove it. And it's not null so it doesn't detect it as useless.
Code which doesn't work :
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
if(frames[i] == null) {
System.out.println("This jump is useless");
}
}
}
}
Then I tried to get some values of stack to manually calculate but without any success (I found that but I cannot port the code to use it on jumps ASM Get exact value from stack frame):
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
// getStackSize() returns 2 so -> 0 and 1
frames[i].getStack(0); // this is probably 1
frames[i].getStack(1); // this is probably 10
// but it returns a BasicValue so I can't check if the code works or not (we cannot get values)
}
}
}
And the last thing I tried was to get the size of the instructions which are used by the jump to delete them (of course it doesn't detect if it's a useless code but I can at least delete it).
In fact I tried to create a method which returns a constant int so I can detect if getValue is called in the instructions of the jump (if I detect the invoke, I delete the instructions of the jump and the jump itself of course):
Example:
if(1 > getValue()) { //getValue() returns 10
return;
}
Code:
Analyzer<BasicValue> an = new Analyzer<BasicValue>(new BasicInterpreter());
Frame<BasicValue>[] frames = an.analyze(cn.name, mn);
ArrayList<AbstractInsnNode> nodesR = new ArrayList<>();
for (int i = 0; i < frames.length; i++) {
if ((mn.instructions.get(i) instanceof JumpInsnNode)) {
if (mn.instructions.get(i).getOpcode() >= IFEQ && mn.instructions.get(i).getOpcode() <= IF_ACMPNE) {
ArrayList<AbstractInsnNode> toRemove = new ArrayList<>();
for (int ia = 1; ia < frames[i].getMaxStackSize() + 2; ia++) { // I started from 1 and added 2 to getMaxStackSize because I wasn't getting all the instructions
toRemove.add(mn.instructions.get(i - ia));
}
toRemove.add(mn.instructions.get(i)); // I add the jump to the list
for (AbstractInsnNode aaa : toRemove) {
if (aaa.getOpcode() == INVOKESTATIC) { // the invokestatic is getValue
for (AbstractInsnNode aaas : toRemove) {
nodesR.add(aaas);
}
break;
}
}
}
}
}
for (AbstractInsnNode aaas : nodesR) {
mn.instructions.remove(aaas);
}
} catch (AnalyzerException e) {
e.printStackTrace();
}
This code is probably horrible and not optimized but I tried a LOT of things without any success. The getMaxStackSize() doesn't return a number which is 100% correct (sometimes it doesn't take additions etc so it deletes instructions such as labels etc...).
What I'm trying to do:
Parsing through a method and check if a conditional jump will always be false (so the code inside will never gets executed) then remove it.
I tried two different way:
Use a BasicInterpreter to check if this jump will get executed with constant values then try it to see if it will always be false
Check if the jump contains a certain method (for example getValue() which returns 10 and compare if it's less than 1) then remove it
What I don't understand :
I think that there is frames in each instructions and that it contains the local variables table and the values that the frame is using – StackMap ? - ( for example if the instruction compare if an int is less than another it would return [II] right ?
I don't know if I can use a BasicInterpreter to test if the two constant ints always return the same result
StackMap = the Stack ? or it's different like the StackMap is a part of the stack which contains the needed values for the instruction ?

Java: ArrayList says index 0 doesn't exist unless I include a String in the parent loop

I am in class, and am trying to complete a chapter exercise, but am having some troubling difficulties.
The assignment requests:
Modify the existing ArrayList's contents, by erasing 200, then inserting 100 and 102 in the shown locations. Use ArrayList's remove() and add() only. Sample output of below program:
100 101 102 103
Here is the program it provides, with my part included:
import java.util.ArrayList;
public class ArrayListADT {
public static void printArray(ArrayList<Integer> numsList, int numOfElem) {
int i = 0;
for (i = 0; i < numOfElem; ++i) {
System.out.print(numsList.get(i));
System.out.print(" ");
}
System.out.println("");
}
public static void main (String [] args) {
ArrayList<Integer> numsList = new ArrayList<Integer>();
int numOfElem = 4;
numsList.add(new Integer(101));
numsList.add(new Integer(200));
numsList.add(new Integer(103));
// I can only access code below this point---------------------------
int j = 0;
try {
for (j = 0; j < numOfElem; j++) {
if (numsList.get(j).equals(200)) {
numsList.remove(j);
numsList.add(1, new Integer(102));
numsList.add(0, new Integer(100));
}
printArray(numsList, numOfElem);
}
} catch (Exception e) {
// Catch whatever exception our code is producing
// Print the error and see what happens.
System.out.println(e);
}
// I can only access code above this point---------------------------
printArray(numsList, numOfElem);
return;
}
}
When I run this code, the program gives me the right input and passes, but gives me an exception:
100 101 102 103
Runtime error (commonly due to an invalid array/vector access, divide by 0, etc.).
I've used the good ol power of unit testing to discover that the culprit is:
numsList.add(0, new Integer(100));
I don't know why! In case it was a syntax error on my part, I tried to switch its position with the other add() in the statement block, but it still only reacted to my attempt to add() to 0. What did I do wrong? I've tried fixing it with a similar problem's solution and changed ++j to j++, but got no solution from this.
OUTPUT AFTER RUNNING UPDATE 1:
✖ Runtime error (commonly due to an invalid array/vector access, divide by 0, etc.).
It doesn't seem to like the try/catch.
Why do you need a loop here? You can just directly remove and then add the new elements:
numList.remove(1);
numList.add(0, new Integer(100));
numList.add(2, new Integer(102));
And you will satisfy your task's requirements
Edit for discussion below:
Put all your code in a try/catch block (don't worry if you don't know what it is just yet, and see if you get more detailed error messages):
try {
// Put your code here and include the printArray() function
} catch (Exception e) {
// Catch whatever exception our code is producing
// Print the error and see what happens.
System.out.println(e);
}
See what the output is and update the question
The for loop does not look like the correct way to do. You can use
if ((index = indexOf(new Integer(200))) != -1)
{
remove(index);
// add methods..
}

Looping through multiple ArrayLists

I had asked the same question in another forum, but dint get any suitable answers...so Im posting it here. I have the following program:
public void execute(){
public static ArrayList<Long> time = new ArrayList<Long>();
public static ArrayList<Integer> state = new ArrayList<Integer>();
public static ArrayList<Integer> cpu = new ArrayList<Integer>();
for(int i=0; i<time.size(); i++){
if(cpu.get(i).equals(get)){
Long next_time = time.get(i);
Integer next_func = state.get(i);
Integer next_proc = cpu.get(i);
if(next_time.equals(g) && (next_func.equals(test1.func_num))){
Integer func_next = stt.get(i+1);
if(func_next.equals(0)||(func_next.equals(next_func))) {
System.out.println("here");
}
else
System.out.println("here");
if(cpu.get(i+2).equals(get))
if(stt.get(i+2).equals(func_next) || (stt.get(i+2).equals(0)))
System.out.println(stt.get(i+2));
}
}
}
What I want to do is this: I get the value of time, cpu and state from the user. find the match in the arraylist for the corresponding values, then I want to loop through the arraylists for only those values which match the 'cpu'. All the ArrayLists are of same size and contain values corresponding to each other at any given index. How can I do this?
Example:
The ArrayLists contain various values as follows:
time = 1 cpu = 12 state = 24
time = 2 cpu = 12 state = 4
time = 5 cpu = 13 state = 23
time = 6 cpu = 13 state = 26
time = 8 cpu = 11 state = 34
time = 11 cpu = 12 state = 54
time = 13 cpu = 12 state = 56
time = 14 cpu = 11 state = 58
time = 15 cpu = 15 state = 46
This is the situation. And I get value from the user as time=2 cpu=12 state =4....I find the match and after that I want to look for all values corresponding to cpu=12 only..
Base more on the description then code example
You get a input in form of time, cpu and state form user.
You want to find match for those input criteria.
To be able to do that easily, You should create a type for that.
public class Data {
private final int cpu;
private final long time;
private final int state;
public Data(int cpu, long time, int state) {
this.cpu = cpu;
this.time = time;
this.state = state;
}
//add implementation for equals and hashcode methods.
}
The equals and hash code method are responsible to define unique value for object. So when you create an object with the same input the should generate same hashcode.
The you create your collection with those elements
Set<Data> storage = new HashSet<Data>();
in this storage, you should store all data that you want to execute search on.
The search is simple. You create a search item
Data searchItem = new Data(user.getCpu(), user.getTime(), user.getState());
if(storage.contains(searchItem)) {
// action on true
} else {
// action on false
}
Implementing hash code
EDIT:
Q: How to perform on all items for given CPU ?
To support such operation you must have in your code a structure that can deliver you some sort of data based on decision. Typically for this operation is used type Map. This type allow to gather under a key reference to value. The value can be a collection of objects.
Map> dataMap = new HashMap<>();// Java diamond notation.
or you can use [Multimap] from guava.
When you find the match, you do this:
//once you have the index in a Integer var called myVal
Set<Integer> indexes = new HashSet<Integer>();
for(int i=0; i<time.size(); i++){
if (cpu.get(i) == myVal) {
indexes.add(i);
}
}
Now you can use the set of indexes:
for (Integer index: indexes) {
//do whatever
}
This is O(time.size()). Hope this helps
Java is pure oo language. It means not only you must write in Object Oriented Style, but also think everything as objects like real world. Before finding how to solve this problem, I would like to advise you that you should read carefully OOP and Connections framework in Java.
Something like this should work:
bool matchFound = false;
for (int i = 0; i < time.size(); i++) {
long thisTime = time.get(i);
int thisState = state.get(i);
int thisCpu = cpu.get(i);
if (matchFound) {
if (thisCpu == userCpu) {
System.out.println("Time: " + thisTime + " "
+ "State: " + thisState + " "
+ "Cpu: " + thisCpu);
}
} else {
matchFound = (thisTime == userTime
&& thisState == userState
&& thisCpu == userCpu);
}
}

Categories

Resources