implementation problem and code optimization - java

I'm studying CS and am still a Java / programming noob, we've got following code in class and have to explain the problems with the following method and are supposed to optimize it:
public static void printData(int[] list) {
int i = 0;
do {
System.out.println(list[i++]);
} while (i < list.length);
}
So, my first thought is that it's of course possible to use a do-while loop, but that I would have used a for loop such as:
public static void pd(int[] list) {
for (int i = 0; i < list.length; i++)
System.out.println(list[i]);
}
for optimization.
Now, the other method is also possible tho and I cannot figure out the problem with it, maybe that it's not too compatible because of the static declaration, but I'm starting to wrap my head around how to deal with calling non-staticmethods from main, if you have any other advice, I've got open ears.

I will not post code here because it sounds like it is a homework. Anyway I'll give you some hints to work on:
What happens in the method provided "printData" if the length of the input array is 0?
What if the list you're getting as input is null?
About the thing with non-static methods, they can only be called upon the instance on the class and not independently.
You can find more in this other question on StackOverflow
Best,

Related

How do I fix this stack overflow error in my code below?

I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.

Java Recursive function sometimes working

I've called upon what I've learned so far and still can't fix this so decided to come here.
A BasicBlock object is referenced by an integer and holds references to the 'addresses' of more blocks in a list. I want to obtain the addresses that they hold reference to and i thought to do this recursively. It is possible for one BasicBlock to hold reference to 0 or more other blocks.
The below recursive function getFunctionReferences keeps returning a stack overflow error, yet manages to work sometimes.
Map<Integer,BasicBlock> blockList blockList = new TreeMap<Integer,BasicBlock>();
public HashSet<Integer> getAssociatedAddresses(int function) {
HashSet<Integer> blockAddresses = new HashSet<Integer>();
getFunctionReferences(this.blockList.get(function),blockAddresses);
return blockAddresses;
}
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
blockAddresses.add(x);
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
I know that I am doing something wrong with this call, especially as there is no base case. But I don't know how to deal with recursion when it is in a loop like this....nor do I know a suitable base case.
Help massively appreciated.
Thanks
If you have cycles (for example block 1 references block 2 which references block 3 which references block 1), you'll get infinite recursion leading to StackOverflowError.
To avoid that, you can take advantage of the HashSet of visited blocks which you maintain. You can simply check if a block was already visited and avoid making another recursive call if it was:
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
if (blockAddresses.add(x)) { // only make a recursive call if x wasn't already
// in the Set
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
}

Re/Create an immutable object that contains an immutable object list

Background
I am trying to create an immutable object that contains a list of immutable objects, as well as object type totals within the list.
I created a slightly sudo gist to try and show what I mean.
Gist - Adjusting an immutable object that contains an immutable object list.
Explanation
My example shows how I'm currently doing it, it does work. However not for all cases.
My VeggieCartView will have a recyclerview that gets filled with a new/saved VeggieCart.
Each VeggieCart has a list of veggies. Veggie totals etc...
I then have a helper class VeggieChanger, it contains an rx.Consumer<Veggie[]> that gets set and accepts any 1:1 veggie changes from the veggie views.
The VeggieCartView sets the consumer so when any one veggie changes, it creates an updated cart using the changes' corresponding cart factory method. The adapter is used to change/retrieve its list.
Working and not
This works well for changing one at a time, however batching changes is throwing concurrency exceptions.
I realize my gist is not runnable and doesn't show most boilerplate, and that I may be fundamentally wrong with some or all of my approaches. With that said I still hope someone can give me advice on how to better implement what I'm trying to do.
If more information is needed to understand, please ask. Thank you for anybody who does have help to offer,
Jon.
I ended up figuring out my main issue.
By adding this to my VeggieCartView:
public void bagAllCanned() {
final Veggie[] canned = new Veggie[cart.canTotal()];
final Veggie[] bagged = new Veggie[canned.length];
int t = 0;
final List<Veggie> veggies = cart.veggies();
for (int i = 0; i < veggies.size(); i++) {
final Veggie veggie = veggies.get(i);
if (veggie.canned()) {
canned[t] = veggie;
if (veggie instanceof Potato)
bagged[t] = Potato.can(veggie);
else if (veggie instanceof Tomato)
bagged[t] = Tomato.can(veggie);
t++;
}
}
for (int i = 0; i < canned.length; i++) {
veggieChange(canned[i], bagged[i]);
}
}
It fixes the concurrency errors.
I'm still unsure if my approach is correct or not. So even though the question is mostly answered, opinions are still VERY welcome.

How to use Caliper benchmark beta snapshot without maven?

I have been asked to use Google's Caliper project to create a few microbenchmarks. I would very much like to use the annotation features of the newest beta snapshot, but aside from a few small examples I am having trouble finding good documentation on how to actually run the thing... There is a video tutorial up which instructs users on the new maven integration feature, which I was also asked NOT to use.
Right now I just have a small example stripped from one of theirs, modified with some other information I gleaned from another SO question:
public class Benchmarks {
public class Test {
#Param int size; // set automatically by framework
private int[] array; // set by us, in setUp()
#BeforeExperiment void setUp() {
// #Param values are guaranteed to have been injected by now
array = new int[size];
}
#Benchmark int timeArrayIteration(int reps) {
int dummy = 0;
for (int i = 0; i < reps; i++) {
for (int doNotIgnoreMe : array) {
dummy += doNotIgnoreMe;
}
}
return dummy;
}
}
//(Questionable practice here?)
public static void main (String args[]) {
CaliperMain.main(Test.class, args);
}
}
Running it gives me the message that I did not set a default value for size. I am having trouble tracking down where I should be putting it.
Removing "size" entirely by commenting out the #Param line and giving a hard value to the array declaration in setUp just leads to it deciding that there are "No Experiments to be done," which makes sense, I suppose.
If there are any up-to-date resources or tutorials that could point out what I am doing wrong (probably a whole lot, honestly) I would be very appreciative.
EDIT:
I have updated to this as per some advice:
public class Benchmarks {
#Param({"1", "10", "1000"}) int size; // set automatically by framework
private int[] array; // set by us, in setUp()
#BeforeExperiment void setUp() {
// #Param values are guaranteed to have been injected by now
array = new int[size];
}
#Benchmark int timeArrayIteration(int reps) {
int dummy = 0;
for (int i = 0; i < reps; i++) {
for (int doNotIgnoreMe : array) {
dummy += doNotIgnoreMe;
}
}
return dummy;
}
}
I am running through the beta snapshot and passing in the Benchmarks class as an argument. I receive the following:
Experiment selection:
Instruments: []
User parameters: {size=[1, 10, 1000]}
Virtual machines: [default]
Selection type: Full cartesian product
There were no experiments to be performed for the class Benchmarks using the instruments [allocation, runtime]
It doesn't seem to be detecting any Instruments. I am not passing any in, as it's mentioned in the documentation that it simply uses default allocation, runtime (which is fine for my purposes).
DOUBLE EDIT: Found that problem, stupid mistake. Will do a quick write-up once I confirm it.
Running it gives me the message that I did not set a default value for size.
Parameters are set either from default values:
#Param({"1", "10", "1000"}) int size;
Or by passing values via the the -D flag. E.g.: -Dsize=1,10,1000. Enums and booleans get special treatment in that it uses all possible values without having to list them in the annotation.
Removing "size" entirely by commenting out the #Param line and giving a hard value to the array declaration in setUp just leads to it deciding that there are "No Experiments to be done," which makes sense, I suppose.
The issue is likely that that your benchmark is an inner class and needs a reference to the enclosing class (though this should have been an error). Either make your benchmark class a top-level class (recommended) or make it static.
Also, there is no particular need to include the main method. Invoking CaliperMain with your benchmark class as the first parameter is equivalent.
Running it gives me the message that I did not set a default value for size.
That's very simple:
#Param({"1", "10", "1000"}) int size;
Removing "size" entirely by commenting out the #Param line and giving a hard value to the array declaration in setUp just leads to it deciding that there are "No Experiments to be done," which makes sense, I suppose.
No, it doesn't. Without any params, each benchmark method is to be run exactly once. See the other answer for the solution.
There's a quite some Javadoc, e.g., on #Param. Actually, not so much has changed. Annotations have replaced conventions (now you don't need the time prefix), params stayed the same, setup uses an annotation instead of inheritance.

Tutorials for Java errors and syntax

I am asking for help on self-help, which is kind of an oxymoron. How do I bug you nice folks less by solving more of my own problems?
I am in my last week of Java programming and I am having a huge hurdle with learning Java. I have read all the books but I keep getting hung up on tiny little issues. It is like trying to build a house of cards. I only know about the parts of the syntax and the uses that the book shows. When I am combining things, I run into horrible hurdles. I try for hours of tinkering to figure them out. The sun docs only show basic uses that don't seem to help
Here is what I would like:
When I am trying something and it doesn't work like the following manipulations of an array list, I want to find a place or program that can show examples code of things like adding an additional class instance to an arrayList. Where can I learn concisely about this without having to ask a question or 2 for every syntax error? Where is the Google for Java? Is there a program that will take your errors and show you how to fix them (or offer suggestions)?
/tmp/jc_4083/Inventory.java:101: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
^
/tmp/jc_4083/Inventory.java:110: array required, but java.util.ArrayList found
if (p != dvdlist[i]) {
^
/tmp/jc_4083/Inventory.java:111: array required, but java.util.ArrayList found
temp[i-adj] = dvdlist[i];
^
/tmp/jc_4083/Inventory.java:115: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
Here is my code for this class if anyone is interested in looking at it for me:
//Contruct inv and allow for methods add, get, size, sort, and value
import java.util.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
public class Inventory
{// class Inventory
private ArrayList<RatedDVD> dvdlist;// declare dvdlist as ArrayList of RatedDVD
private int numDVDs;
public Inventory()
{// method Inventory
dvdlist = new ArrayList<RatedDVD>();
}// end method
// add & get
public RatedDVD get(int i){return dvdlist.get(i);}// method get
public void add(DVD d){
dvdlist = dvdlist d;
sort();
}// method add
public double value()
{// method value
double total = 0.0;
for (int i = 0; i < dvdlist.size(); i++)
{// for every pass thru dvdlist add total
// [DEBUG] consider enhanced for
total += get(i).feeValue();
}
return total;
}// end method value
public void sort()
{// method sort
// [DEBUG] consider optimization
int n = dvdlist.size();
for (int search = 1; search < n; search++)
{// for do the following and increment till dvdlist has been searched
for (int i = 0; i < n-search; i++)
{// for step through comparison for entire dvdlist
if (dvdlist.get(i).getName().compareToIgnoreCase(dvdlist.get(i+1).getName()) > 0)
{// if swap necessary then swap
RatedDVD temp = dvdlist.get(i);
dvdlist.set(i,dvdlist.get(i+1));
dvdlist.set(i+1,temp);
}// end if swap
}// end for compareto
}// end outer for
}// end method sort
public int size(){return dvdlist.size();}// method size
public void save() {
save(true);
}
// save it to C:\data\inventory.dat
public void save(boolean saveagain) {
try {
BufferedWriter w = new BufferedWriter(new FileWriter("c:\\data\\inventory.dat"));
for (int i = 0; i < size(); i++) {
RatedDVD dvd = get(i);
w.write( dvd.getItem() + "\n");
w.write( dvd.getName() + "\n");
w.write( dvd.getRating() + "\n");
w.write( dvd.getUnits() + "\n");
w.write( dvd.getPrice() + "\n");
w.write( dvd.value() + "\n");
w.write( dvd.fee() + "\n");
w.write( dvd.feeValue() + "\n");
w.newLine();
}
// total value of it
//w.write( value() + "\n");
w.close();
} catch (Exception ex) {
if (saveagain) {
new File("c:\\data\\").mkdir(); // make file if doesn't exist
save(false);
}
}
}
public int search(String name) {
for (int i = 0; i < size(); i++) { // check if name string is equal
if (get(i).getName().equalsIgnoreCase(name)) return i;
}
return -1; // we didn't find anything
}
// add a new dvd to the end, increasing the array size
public void add(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()+1];
for (int i = 0; i < dvdlist.size(); i++) {
temp[i] = dvdlist[i];
}
temp[temp.length-1] = p; // add it at the end
dvdlist = temp;
}
// remove a DVD from the array, and shrink the array size
public void delete(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()-1];
int adj = 0;
for (int i = 0; i < dvdlist.size(); i++) {
if (p != dvdlist[i]) {
temp[i-adj] = dvdlist[i];
}
else adj = 1;
}
dvdlist = temp;
}
public int highestNumber() {
int numb = 0;
for (int i = 0; i < dvdlist.size(); i++) {
if (get(i).getItem() > numb) {
numb = get(i).getItem();
}
}
return numb;
}
}// end class inventory
The dvdlist is an ArrayList, which implements the Collection interface, not an Array (BTW, and this is known as the "program to an interface, not an implementation" principle, you should decalare dvdlist as a java.util.List):
private ArrayList<RatedDVD> dvdlist;// declare dvdlist as ArrayList of RatedDVD
Have a look at the methods on the Collection interface, you'll find everything you need for adding and removing elements.
So, to add a RatedDVD, you don't need to use a temporary array of RatedDVD that won't fit anyway into an ArrayList like you're doing here:
// add a new dvd to the end, increasing the array size
public void add(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()+1];
for (int i = 0; i < dvdlist.size(); i++) {
temp[i] = dvdlist[i];
}
temp[temp.length-1] = p; // add it at the end
dvdlist = temp;
}
Instead, just call the add(Object o) method on dvdlist.
To delete a RatedDVD instance, use the remove(Object o) method on dvdlist.
For the search() method, consider using contains(Object o) on dvdlist.
If you need to iterate over a collection, use an Iterator:
for (Iterator iter = dvdlist.iterator(); iter.hasNext();) {
RatedDVD ratedDVD = (RatedDVD) iter.next();
//rest of the code block removed
}
Or even faster now with Java 5+ and Generics:
for (RatedDVD ratedDVD : dvdlist) {
// rest of the code here
}
Really, you need to dig the the Collection Framework.
The compiler errors seem to be quite descriptive of what you're doing wrong, but I can see why you might be confused about how to do it right. You seem to be misunderstanding how an ArrayList is meant to be used. If you look at the docs, you will see it has methods add() and remove() that do the operations you've created add() and delete() methods for. You're attempting to treat the ArrayList as if it is a raw array. Don't do that; use the methods provided by the API. Not only will this solve your errors, but it will make your code cleaner and clearer to future programmers.
Actually, the compiler error is very clear:
/tmp/jc_4083/Inventory.java:101: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
It says "incompatible types" and that it expected a java.util.ArrayList but found instead a RatedDVD[].
Your problem is simply that, unlike in languages like Python, Java does not treat lists and arrays interchangeably. They are completely different things - arrays are special language-level constructs, while ArrayList is a class like any other.
So you cannot assign an array to a variably of type list. You either have to decide on using only one of these two types throughout your program, or you have to convert between them manually, using methods such as java.util.Arrays.asList() and List.toArray().
It seems that you're trying to do too advanced things too fast - you should probably look at Sun's Java tutorials first - though they are quite comprehensive and can also be used as a reference for looking up language details. There is also a section about conversion between collections and arrays.
I suggest you use an IDE (like Eclipse, entirely free). It will help you through the API syntax by making suggestions as you type, and show you errors when you type them, so that you can pinpoint exact syntax errors and ask about them. In terms of asking, that is what StackOverflow is for.
Others beat me to your specific syntax question, so I'm just limiting my answer to the general question of how you get help.
To resolve compiler errors, usually it's best to start with the first one and fix it first. After fixing that, the rest of the compiler errors might also be solved, or they might be different kinds of errors.
To understand what some compiler error means, there is an article called Compile and Runtime Errors in Java (PDF) that goes through different kinds of error messages and gives examples of what kind of code may cause them. And as for runtime error messages, Java Glossary has quite a big list of them. They also have a list of compile-time error messages.
So, your problem here is that you're trying to access an ArrayList like an array, which is incorrect because Java doesn't do stuff like that. You need to use list.get(i) to get the ith element in an Array. Similarly, when you tried to set an ArrayList variable to an array, the compiler got mad at you. You need to create a new ArrayList with the contents of temp and then set dvdlist to that, eg. dvdlist = new ArrayList<RatedDVD>(temp);.
As for your continued problems: There is an API Specification for Java which tells you basically how to use all the classes that are included in the Java API. For example, ArrayList is a generic collection which has certain methods and constructors that you need to use. Java does not have operator overloading, so you can't just access elements in a List using array syntax. Also, arrays are their own data type so you can't just treat an ArrayList as an array and vice versa.
It looks like you are confused about the difference between an array and an ArrayList. An array is a static list of elements, and is constructed using the [] symbols. An ArrayList is an object in the Collections system in Java that acts like a size-modifiable array - i.e. it can be indexed into, and can be added onto, inserted into, etc. They are not interchangable.
As to where you can look, etc. If this is your first programming experience, you are not alone. Many compiler errors are less than helpful. One suggestion I can give you that I learned through many years of trial and error - start small and build up. Get a main method that compiles. Then add the first little piece (creating a class for instance). Then add the next piece, and so on. Test as you go, etc. You can google for particular compiler errors - I have been surprised what I have found. Beyond that, a lot of it is trial and error - these are things you learn from experience, and a lot of the speed of "old hands" comes from the long experience of seeing what you can do wrong over and over again, not any sort of innate intelligence. I totally understand your frustration - I felt that way when I was starting out about 15 years ago now (but I was on Borland Pascal - yuck).
One of the biggest issues beginning programmers seem to have is not being able to read and interpret error messages very well.
You would be well served by carefully examining the errors that javac (or any compiler/interpreter) provides. Maybe even start by making some mistakes that you understand in your code (ie, assign an incorrect typed value to a variable, extend a loop beyond the bounds) and see how your compiler handles these.
Try to think in object oriented terms...
It looks to me that something (classwork, I guess) has pushed you into writing an object-oriented program but it's possible that you haven't yet accepted that you will need to think in those terms.
In Java most things are objects, but Java supports primitive types, and arrays of both. It's possible to program in Java in a flat, procedural, mutable way, but also possible to write in an object-oriented functional way. It's possible to do both and get confused, which is where you may be right now.
You are trying to mix the two styles. This isn't always a bad thing, but for coursework we can safely bet the farm that your instructor will want to see more objects and fewer arrays, unless those arrays are the private internal implementation of an object.
So think of the data structures as black boxes with methods, and then see how what you are doing is implementing one yourself.
You have probably been here, but these are the things that you can do with an ArrayList. And you have an ArrayList<RatedDVD> which further restricts what you can do with it. Try to understand this first, and then fix the program to work with the available operations on an ArrayList object.

Categories