Arraylist of Custom Object - java

This is a fairly simple question, but I am a beginner and I've been stuck on this part for hours now. I am not looking for an easy way out, but instead I just want to understand what is happening to my code and why it isn't working. My problem was:
Create a node class with a random number and the current time.
Create a storage class and store those nodes in a list/array.
Use the main class to create 50 nodes and display.
When I run it 50 times and get my list, I made the list print out the time so that I could check to see if my code was running, and they all have the same time. It means that different nodes aren't being stored into my list, and are instead being wiped out each time the loop runs. Why is that?
My code is attached:
Main:
public class NodeSort {
public static void main(String[] args)
{
int c = 0;
while (c < 50)
{
Storage.add();
c++;
}
}
}
Node:
public class Node
{
public static int num;
public static long time;
public Node()
{
num = Random.getNum();
time = System.nanoTime();
}
public static long getTime()
{
return time;
}
public static int getNum()
{
return num;
}
}
Storage:
public class Storage
{
public static ArrayList<Node> list = new ArrayList<>();
public static void add()
{
list.add(new Node());
}
When I do get time for x = 1-50, it prints out the same time 50 times instead of 50 different ones.

They all have the same time value because they're all getting created at almost the same time. System.nanoTime() doesn't guarantee that you'll actually get nanosecond precision, it's up to the operating system's ability to discern time. Most OSes can only provide millisecond resolution. So if all of the calls happen within the same millisecond, you'll get the same values.
As far as the random number is concerned, I don't know--what is the Random class? It's not java.util.Random.
Edit: Oh wait, I see it. You declared num and time as static in your Node class. That means there's only one copy of each in existence. Just remove static from those declarations, and from the methods that return the values.

Related

Question about Berkeley Data Structures Free Online Course (CS61B) Tutorial question on static variables in Java

Note: This is not a homework assignment, but a free course that anyone can access.
The course can be found at: https://sp18.datastructur.es/index.html
The tutorial question can be found at: https://sp18.datastructur.es/materials/discussion/examprep02sol.pdf
Also, the variables are named as such in order to confuse potential students, and I decided not to change it for fear of changing the code resulting in a different output. Also, some of the variables (baby), and method calls were not used at all, but I have retained it in order to keep to the original question.
Q1 Write what the main method will print out once it is executed. It might be helpful to draw box and pointer diagrams to keep track of variables (Spring ’15, MT1)
public class Shock {
public static int bang;
public static Shock baby;
public Shock() {
this.bang = 100;
}
public Shock(int num) {
this.bang = num;
baby = starter();
this.bang += num;
}
public static Shock starter() {
Shock gear = new Shock();
return gear;
}
public static void shrink(Shock statik) {
statik.bang -= 1;
}
public static void main(String[] args) {
Shock gear = new Shock(200);
System.out.println(gear.bang); //300
shrink(gear);
shrink(starter());
System.out.println(gear.bang); //99
}
}
Why is the value of gear.bang 300 instead of 200 + 200? I understand that gear is a static variable, but when using the second constructor, the value 100 should not have been involved at all. I would have thought that the static variable bang would be set as 200, then 200 += 200 will result in the static variable bang being 400 for all instances of Shock class. Why is gear.bang 300 instead?
The second constructor calls starter().
starter() calls new Shock().
The Shock() constructor sets bang to 100. Then 200 is added to bang. So bang is 300.

error: multiply(long) is not public in BigInteger; cannot be accessed from outside package

I'm trying to write a Java method that uses counts the number of ways to sequentially order n distinct objects - a permutation. Every time I try to complile my code, I get an error saying:
multiply(long) is not public in BigInteger; cannot be accessed from outside package.
I tried replacing the line fact = fact.multiply(i); with fact = fact.multiply((long) i); which didn't work either. Does anyone have any ideas?
import java.math.BigInteger;
public class Combinatorics {
public static void main(String[] args) {
// 2.1
System.out.println(CountPerm(9));
}
public static BigInteger CountPerm(int n) {
BigInteger fact = BigInteger.valueOf((long) 1);
for(int i = 1; i <= n; i++){
fact = fact.multiply(i);
}
return fact;
}
}
To multiply BigIntegers, you need give a BigInteger parameter, not a long parameter. The method is BigInteger.multiply(BigInteger).
Change your code to:
fact = fact.multiply(BigInteger.valueOf(i));
As a side note:
BigInteger.valueOf((long) 1); should be replaced by BigInteger.ONE. There is already a predefined constant for one.
Be sure to respect Java naming conventions: CountPerm method should be called countPerm.

Why another branch is unreachable in my code?

Why the output of the following code is always suck. How to get happy as the output? Why the happy branch is unreachable?
public class HowToMakeStackoverflowBetter {
private static final int HUMAN_PATIENCE = 10;
private List<Member> members = new ArrayList<>();
private int atmosphere = -10;
private Random r = new Random();
public HowToMakeStackoverflowBetter(int size) {
for (int i = 0; i < size; i++) { members.add(new Member()); }
}
public Member pick() { return members.get(r.nextInt(members.size())); }
public class Member {
private int patience = HUMAN_PATIENCE;
private Question question = null;
public Member() { patience = r.nextInt(patience+1) + atmosphere; }
public void vote(Question q) {
if (patience >= 0) {
voteUp(q);
} else {
voteDown(q);
}
}
public void ask() {
question = new Question();
for (Member member : members) {
member.vote(question);
}
}
private void voteUp(Question q) { ++q.vote; }
private void voteDown(Question q) { --q.vote; }
public String toString() {
return (question.vote >= 0)? "Happy!" : "Suck!";
}
}
public class Question { private int vote; }
public static void main(String[] args) {
HowToMakeStackoverflowBetter stackoverflow = new HowToMakeStackoverflowBetter(100);
Member me = stackoverflow.pick();
me.ask();
System.out.println(me);
}
}
After a 1000 times loop, it gives us 1000 sucks. I remember 2 or 3 years ago, this was not the case. Something changed.
Two problems. First:
linkedList::linkedList(){
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel.str="I am sentinel!!";
};
sentinel is your member variable, and .last is its pointer to another node. This hasn't been initialised, so trying to use it is undefined behaviour. In practice, it's effectively pointing at a random address in (or out of) memory, and you attempt to dereference the pointer then copy the entire sentinel object over the node at the imagined pointed-to address: i.e. you try to copy the 3 pointers in the sentinel node member variable to a random address in memory.
You probably want to do this:
linkedList::linkedList()
{
sentinel.last = &sentinel;
sentinel.next = &sentinel;
sentinel.str = "I am sentinel!!";
}
Secondly, you explicitly call the destructor for linkedList, which results in undefined behaviour when the compiler-arranged destruction is performed as the object leaves the stack scope it's created in - i.e. at the end of main().
I suggest you change node.str to be a std::string, as in any realistic program you'll want to be able to handle variable text, and not just point to (constant) string literals. As is, if you mix string literals and free-store allocated character arrays, you'll have trouble knowing when to call delete[] to release the memory. You could resolve this by always making a new copy of the string data to be stored with new[], but it's safer and easier to use std::string.
Since you allocated it as a local variable, your mylist will be destroyed automatically upon exiting main. Since you've already explicitly invoked its destructor, that leads to undefined behavior (attempting to destroy the same object twice).
As a quick guideline, essentially the only time you explicitly invoke a destructor is in conjunction with placement new. If you don't know what that is (yet), that's fine; just take it as a sign that you shouldn't be invoking destructors.
You forgot to initialize sentinel
In code below you are trying to initialize sentinel (which is not yet constructed) with sentinel(same thing). So you have to pass something to constructor which can be used to initialize your member variable sentinel
*sentinel.last=sentinel;
Also no need to call destructor like this. Destructor will be called once your myList goes out of scope.
myList.~linkedList();
the program may crash, with this:
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel is not initialized sot i has random value on stack.
You're trying to de-reference the pointers last and next of member variable sentinel when they are not yet initialized.
And these de-references *sentinel.last=sentinel *sentinel.next=sentinel are causing the crash because without assigning the values to pointers you're changing the value pointed by the pointers.
You can do like this
sentinel.last=&sentinel;
sentinel.next=&sentinel;
And as pointed out by other explicit destructor calls aren't need here.

NullPointer in an Class array

I have two java classes. Schedule is the main class that uses an array of Jobs called deadline. I'm having problems putting anything in array. I have a for loop that reads data from a text file (it works fine) and inserts certain data into deadline. I not successfully creating deadline because whenever I want to start inserting into the array I get a NullPointerException. (The code below the ... obviously isn't what I actually coded, but it is still the same situation.)
It has been a while since I've coded in Java, so I might be just overlooking something simple, but I'm not really sure what it could be... Thanks for any help you can give.
public class Schedule {
private Job []deadline;
Schedule (int n){
Job[] deadline = new Job[n];
}
...
int n = 7;
Schedule schedule = new Schedule(n);
deadline[0] = new Job("A",3,40); // This line won't compile. NullPointerException
}
public class Job {
private String name;
private int deadline;
private int profit;
Job(String n, int d, int p){
name = n;
deadline = d;
profit = p;
}
}
You are shadowing deadline in your constructor, so you don't initialize the class member deadline, but the local one. Change it to:
private Job []deadline;
Schedule (int n){
deadline = new Job[n];
// ^^ note - no Job[] here
}

Problem with Priority Queue

I'm trying to use a priority queue in my code, and for some reason when I remove the objects, they aren't in order. Do you know what i"m doing wrong?
Here's my code:
the contructor:
recordedsong = new PriorityQueue<recordedNote>(50, new Comparator<recordedNote>()
{
public int compare(recordedNote n1, recordedNote n2)
{
long l = n1.rt()-n2.rt();
int i = (int)l;
return i;
}
});
where each recordedNotehas a long value that is returned my the method rt().
But when I call
while (!Song.isEmpty())
{
recordedNote temp = (recordedNote)Song.remove();
and then print temp.rt() for each one, all the numbers are out of order. And not just like reverse order, but all over the place, like 1103, 0, 500, 0, 220 orders like that.
Can you see if there's anything wrong with my contructor?
Thanks!
remove should work, and in fact it does work fine in a small example program that I created to help answer this question:
import java.util.Comparator;
import java.util.PriorityQueue;
public class TestPriorityQueue {
public static void main(String[] args) {
long[] noteTimes = {1103L, 0L, 500L, 0L, 220L, 1021212812012L};
PriorityQueue<RecordedNote> noteQueue = new PriorityQueue<RecordedNote>(10,
new Comparator<RecordedNote>() {
#Override
public int compare(RecordedNote o1, RecordedNote o2) {
Long time1 = o1.getTime();
Long time2 = o2.getTime();
// uses Long's built in compareTo method, so we
//don't have to worry as much about edge cases.
return time1.compareTo(time2);
}
});
for (int i = 0; i < noteTimes.length; i++) {
RecordedNote note = new RecordedNote(noteTimes[i]);
System.out.println(note);
noteQueue.add(note);
}
System.out.println();
while (noteQueue.size() > 0) {
System.out.println(noteQueue.remove());
}
}
}
class RecordedNote {
private long time;
public RecordedNote(long time) {
this.time = time;
}
public long getTime() {
return time;
}
#Override
public String toString() {
return "[Time: " + time + "]";
}
}
So this begs the question, why isn't it working for you? Myself, I don't see enough coherent code in your question to be able to answer this. We're not sure what is Song as I don't see this declared as a class or a variable, and I also don't see where you're using your PriorityQueue variable, recordedsong, anywhere. So I suggest you do the same thing as I: create a small compilable runnable program that we can run and modify and that demonstrates your problem, an http://sscce.org
I guess there is a possibility for i getting 0. So modify compare method so that it returns a positive value rather than the result.
Reading the API docs for PriorityQueue, it states the following:
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
My guess is that remove() is not obligated to follow the natural ordering, either.

Categories

Resources