i'm writing a program for a game called 'Trivia'. Below is the source code:
Trivia.java
public class Trivia implements Serializable {
private String question;
private String answer;
private int points;
public Trivia() {
question = " ";
answer = " ";
points = 0;
}
public String getQuestion() {
return question;
}
public String getAnswer() {
return answer;
}
public int getPoints() {
return points;
}
public void setQuestion(String q) {
question = q;
}
public void setAnswer(String a) {
answer = a;
}
public void setPoints(int p) {
points = p;
}
}
Driver.java
public class Driver {
public static void main(String[] args) {
Trivia[] t = new Trivia[5];
for (int i = 0; i < 5; i++) {
t[i] = new Trivia();
}
t[0].setQuestion("How many states are in the US?");
t[0].setAnswer("50");
t[0].setPoints(1);
t[1].setQuestion("Who is the richest person in the US");
t[1].setAnswer("You");
t[1].setPoints(1);
t[2].setQuestion("How many senators come from each state?");
t[2].setAnswer("2");
t[2].setPoints(2);
t[3].setQuestion("What is the largest state?");
t[3].setAnswer("Alaska");
t[3].setPoints(2);
t[4].setQuestion("Who was the thrid president?");
t[4].setAnswer("Thomas Jefferson");
t[4].setPoints(3);
ObjectOutputStream outputStream = null;
try {
outputStream = new ObjectOutputStream(new FileOutputStream("C:\\Work\\workspace\\aman\\src\\trivia\\trivia.dat"));
} catch (IOException e) {
System.out.println("Could not open file");
System.exit(0);
}
try {
outputStream.writeObject(t);
outputStream.close();
} catch (IOException e) {
System.out.println("Writing error");
System.exit(0);
}
ArrayList<Trivia> triviaQuestions = new ArrayList<Trivia>();
try {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("C:\\Work\\workspace\\aman\\src\\trivia\\trivia.dat"));
for(int i=0; i<5; i++){ // Repeats the content of the loop five times
triviaQuestions.add((Trivia) inputStream.readObject());
}
inputStream.close(); // Closes the input stream because it is not longer needed
} catch (IOException | ClassNotFoundException e) {
System.out.println("File not found.");
System.exit(0);
}
Trivia yourRandomTrivia = triviaQuestions.get((new Random()).nextInt(triviaQuestions.size())); // This will be your random question
}
// You did not get an auto complete suggestion because you typed outside of a method
}
noe when I try to run this program, I get an error saying "Ltrivia.Trivia; cannot be cast to trivia.Trivia". The error is thrown in class Driver on line " triviaQuestions.add((Trivia) inputStream.readObject());". I did some research on this and found that 'L' means array of a datatype. But, I have simple created an arrayList of type Trivia and trying to add each element I get from the inputStream by casting them to Trivia class.
Does anybody have any suggestions on this?
Your code is writing an Array of Trivia objects.
Then you try to read and add that to a list of Trivia objects.
You cant add arrays of Trivia to an List of Trivia!
And that is what the message is telling you: you cant cast the type Trivia[] to Trivia. Because an array of X is not the same as a single X.
One solution: instead of writing t as a whole, you can simply iterate t and write the members of the array. Of course that means that you have to somehow remember how many elements you wrote into that stream. You could get there by first writing an Integer object representing the number of Trivia objects that will follow.
The other solution: just read back that Trivia[]; and iterate it then; to add the various Trivia objects one by one.
Edit: on your comment: when you read from an ObjectInputStream you get back those things that you put into your file/stream earlier on. As said: your code puts a single object of type ARRAY of Trivia into bytes ... and then you want to read that thing back as a single Trivia object! That does not work!
Related
I'm making a guess the movie game in which i take a list of movies from a text file. I have two classes for it Game for getting a random movie and Main for the rest of the game. Now i thought of adding a choice for hollywood or bollywood movies by changing the text files in Game. I take 'h' or 'b' respectively as inputs. I call the constructor of Game with parameters to choose file accordingly but it doesn't work and ALWAYS the file is null and showing NullPointerException.
This image showing what happens during debugging. It skips the setMovieList and constructor and comes to the next line
EDIT: I am new to OOPs so please bear with me. I just saw during debugging that the debugger first goes to the class fields and THEN to the constructor, I was actually trying to use file(which is inside the constructor) for the initialization of other fields because of which its value was null and was showing NullPointerException.
Now my question really remains how to use file and noOfMovies to initialize other fields in Game.
//showing the setter method that i tried
//Main class
/*only showing the part having Game class*/
//making an object of Game class to get a random movie from the file
System.out.println("Enter 'h' for hollywood and 'b' for bollywood ");
Scanner input = new Scanner(System.in);
char genre = input.next().charAt(0);
Game newGame = new Game(genre);
//Game class
public class Game
{
public Game(char genre)
{
setMovieList(genre);
}
File file;
int noOfMovies;
public void setMovieList(char genre)
{
if(genre == 'h')
{
this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\hollywoodMovies.txt");
this.noOfMovies = 30;
}
else if(genre == 'b')
{
this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\bollywoodMovies.txt");
this.noOfMovies = 20;
}
// EDIT ------> I want to initialize the below fields <-------
private Scanner scan = new Scanner(this.file);
private int lineCount = 0;
int random = (int)(Math.random()*noOfMovies)+1;
//array for storing the movie titles
private String[] movieArray = new String[noOfMovies];
}
I'm not sure.. maybe you want to get a result like this:
GAME CLASS
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Game {
private File file = null;
//private int noOfMovies = 0;
private List<String> movies= null;
FileInputStream read = null;
public Game(char genre) {
movies = getMovieList();
System.out.println(movies);
}
public void setMovieList(char genre) {
if (genre == 'h') {
this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\hollywoodMovies.txt");
// this.noOfMovies = 30;
} else if (genre == 'b') {
this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\bollywoodMovies.txt");
// this.noOfMovies = 20;
}
}
public List<String> getList() {
List<String> movieList = new ArrayList<>();
String[] values = null;
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
values = line.split(";");
movieList.add(values[0]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return movieList;
}
public String getMovie(){
System.out.println(movies.size());
int min = 1;
int max = movies.size();
int random = min + (int) (Math.random() * (max - min));
System.out.println(random);
String title = movies.get(random);
return title;
}
}
MAIN CLASS
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Enter 'h' for hollywood and 'b' for bollywood ");
Scanner input = new Scanner(System.in);
char genre = input.next().charAt(0);
Game newGame = new Game(genre);
String randomMovie = newGame.getMovie();
System.out.println(randomMovie);
}
}
Note i've used List data structure in place of array but it is obviously up to you... let me know if this may look like what you are trying to do... some other improvements can certainly be made but should work.
Also it assumes you have a txt file with movie titles separated by semicolon...otherwise you have to adjust the split method in the getList one..
Furthermore this way you no longer need the noOfMovies field cause it takes automatically the list size.
Hope it helps...
The problem is that the fields are initialised before the constructor is called.
There are a number of things you should do:
Don't call getters and setters from a constructor. See this question: Should I use getters and setters in constructors?
If you are doing complex initialisation logic, do it all in the constructor. Only initialise fields directly with very basic values (not ones that depend other fields). In your case, it will be easier just to do everything in the constructor. This avoids the problem that you change your code to modify a value in the constructor and some field initialisation stops working.
I had an ArrayList that was being operated on by multiple threads, which wasn't working as the ArrayList isn't synchronized. I switched the list to a Vector as instructed by my professor. Vector is synchronized, but I'm having exceptions thrown related to synchronization.
Why is this happening, and how can I avoid concurrency exceptions in my code? I don't want to just play around until something works, I want to do the best thing. Thanks!
Exception:
Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Vector.java:1184)
at java.util.Vector$Itr.next(Vector.java:1137)
at BytePe4D$ReadInts.run(BytePe4D.java:64)
Code:
import java.io.*;
import java.util.Vector;
public class BytePe4D {
private Vector<Integer> numbers;
public static void main(String[] args) {
new BytePe4D();
}
public BytePe4D() {
// Create ArrayList and reset sum
numbers = new Vector<Integer>();
// Call addInts 8 times, with filenames integer1.dat through integer8.dat
for (int i = 1; i <= 8; i++) {
File file = new File("PE Data/integer" + i + ".dat");
ReadInts thread = new ReadInts(file);
thread.start();
}
}
/** Represents a Thread instance */
class ReadInts extends Thread {
File file;
public ReadInts(File _file) {
file = _file;
}
#Override
public void run() {
int count = 0; // track number of records read
int sum = 0;
try {
// Open stream to binary data file integer1.dat
FileInputStream in = new FileInputStream(file);
// Buffer the stream
BufferedInputStream bin = new BufferedInputStream(in);
// Access the primitive data
DataInputStream din = new DataInputStream(bin);
try {
// Read file until end reached
while (true) {
numbers.add(din.readInt());
count++;
}
} catch (EOFException eof) {
// System.out.println("End of file reached.");
} finally {
// Close streams
din.close();
}
} catch (FileNotFoundException fnf) {
System.out.println("File does not exist: " + file.getName());
return;
} catch (IOException ioe) {
ioe.printStackTrace();
}
// Calculate sum of numbers read
for (int num : numbers) {
sum += num;
}
// Write info
System.out.println(
String.format("%s%s%-5s%s%-8d%-5s%s%-12d%-5s%s%d",
"Filename = ", file.getName(), "",
"Count = ", count, "",
"Sum = ", sum, "",
"In List = ", numbers.size()));
}
}
}
From the docs:
if the vector is structurally modified at any time after the iterator
is created, in any way except through the iterator's own remove or add
methods, the iterator will throw a ConcurrentModificationException.
The following code creates an iterator under the covers:
for (int num : numbers) {
sum += num;
}
So when one threads modifies the vector (by adding elements) while another vector is iterating it - you'll see a ConcurrentModificationException
There are different options to solve it, one way could be to read from a file into another vector and when the reading is done assign this other vector to numbers (since assignment is an atomic operation). Keep in mind that in order for the change to be visible to other threads you'll need to declare numbers as volatile.
Your code seems wrong.
I don't see why you need a shared vector, if each thread is to calculate the sum of records from an individual file. On the other hand, if you want to calculate the sum of records from all files, you should do it after every thread has completed.
Depending on which you want, you can either 1) create a vector for each thread and calculate the sum for each file or, 2) in the main thread, wait for all threads to complete then calculate the sum for all files.
I've already made another question close to this one several minutes ago, and there were good answers, but it was not what I was looking for, so I tried to be a bit clearer.
Let's say I have a list of Thread in a class :
class Network {
private List<Thread> tArray = new ArrayList<Thread>();
private List<ObjectInputStream> input = new ArrayList<ObjectInputStream>();
private void aMethod() {
for(int i = 0; i < 10; i++) {
Runnable r = new Runnable() {
public void run() {
try {
String received = (String) input.get(****).readObject(); // I don't know what to put here instead of the ****
showReceived(received); // random method in Network class
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
tArray.add(new Thread(r));
tArray.get(i).start();
}
}
}
What should I put instead of ** ?
The first thread of the tArray list must only access the first input of the input list for example.
EDIT : Let's assume my input list has already 10 elements
It would work if you put i. You also need to add an ObjectInputStream to the list for each thread. I recommend you use input.add for that purpose. You also need to fill the tArray list with some threads, use add again there.
Here's the solution:
private void aMethod() {
for(int i = 0; i < 10; i++) {
final int index = i; // Captures the value of i in a final varialbe.
Runnable r = new Runnable() {
public void run() {
try {
String received = input.get(index).readObject().toString(); // Use te final variable to access the list.
showReceived(received); // random method in Network class
} catch (Exception exception) {
exception.printStackTrace();
}
}
};
tArray.add(new Thread(r));
tArray.get(i).start();
}
}
As you want each thread to access one element from the input array you can use the value of the i variable as an index into the list. The problem with using i directly is that an inner class cannot access non-final variables from the enclosing scope. To overcome this we assign i to a final variable index. Being final index is accessible by the code of your Runnable.
Additional fixes:
readObject().toString()
catch(Exception exception)
tArray.add(new Thread(r))
I am stucked by coding and I need your help.
Ok first of all I have an array variable under a class.
I get the values from excel and put inside the nodename array like as follows.I shortened the following codes.
Following class Readexcel is also under ConfigGenerator Class.
class ReadExcel {
private String inputFile;
public void setInputFile(String inputFile) {
this.inputFile = inputFile;
}
public void read() throws IOException {
File inputWorkbook = new File(inputFile);
Workbook nodes;
try {
nodes = Workbook.getWorkbook(inputWorkbook);
// Get the first sheet
Sheet nodessheet = nodes.getSheet(1);
String[] nodename = new String[nodessheet.getRows()];
for (int i = 1; i < nodessheet.getRows(); i++) {
int j = 0;
Cell x1a = nodessheet.getCell(0, i);
nodename[j] = x1a.getContents();
j++;
// System.out.println(nodename[j]);
}
} catch (BiffException e) {
// e.printStackTrace();
}
}
}
But my problem is to reaching this variable from a button action.
public class ConfigGenerator extends javax.swing.JFrame {
public ConfigGenerator() {
initComponents();
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
private void generateActionPerformed(java.awt.event.ActionEvent evt) {
try {
Writer output = null;
for (String name: Generator.ConfigGenerator.ReadExcel.nodename[????]){
System.out.println(name);
}
output.close();
System.out.println("Your files has been written.");
} catch (IOException ex) {
Logger.getLogger(ConfigGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
The parts that i added question mark is my problem for the last 2 days I am tring but couldn't get the values from that array.
First I need to get lenght of array and second the values :)
Thank you very much for your help in advance.
Ok I edited the question by adding the whole section with codes.
Maybe you mean that you want to get the array lenght using nodename.length, but I have two issues with your code:
First you access nodename as an array local to your action, then later access it as a static variable of class ConfigGenerator, which means you are accessing two different arrays.
Also, you access the nodename array as a static variable (although even the .class is not necessary), but you mentioned it as a "array variable" which means you need first to create a new instance of class ConfigGenerator, initializing the array nodename, and then you can use it in other classes.
First of all, the way to retrieve the length of an array in Java is
nodename.length
not
nodename.getlength()
But you could also use the shortened syntax to loop through all elements in the specific array:
for (Object obj : array) {
System.out.println(obj);
}
In your case it would be:
for (Object obj : ConfigGenerator.nodename) { //replace Object with your datatype
System.out.println(obj);
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
OK so Searching is my weak area in Java and could really use help as to where to begin on this Assignment!!
The data member n is no longer needed.
The LinkedList should be created and assigned to theList in the constructor rather than in run().
makeScanner(), getPerson(), and main() should not be modified. The Person and FileFormatException classes should also not be modified.
display() will no longer compile since theList is no longer an array. You can either change it to use a foreach or simply remove it.
run() has a loop that adds Person objects to the array. Change it so that it adds these to a list instead. Consider:
theList.add(p);
The variables index and n are no longer necessary.
Modify search() to perform the linear search on a list rather than an array. The easiest way is to use a foreach and return the correct Person if found. If the correct Person is not found, it should return null as before.
This is what I have so far:
import java.util.LinkedList;
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
public class ContactList {
private LinkedList<Person> theList;
private int n; // the number of Persons in theList
private Scanner keyboard;
public ContactList() {
keyboard = new Scanner(System.in);
} // no-arg constructor
// Returns a Scanner associated with a specific text-based URL
// online.
private Scanner makeScanner() throws IOException {
final String source =
"http://userpages.umbc.edu/~jmartens/courses/is247/hw/05/05.txt";
final URL src = new URL(source);
return new Scanner(src.openStream());
} // makeScanner()
// Return a Person instance based upon data read from the given
// Scanner.
private Person getPerson(final Scanner in) throws FileFormatException {
if (!in.hasNextLine())
return null;
String line = in.nextLine().trim();
int key = Integer.parseInt(line);
String name = in.nextLine().trim();
String mail = in.nextLine().trim().toLowerCase();
if (in.hasNextLine()) {
String empty = in.nextLine().trim(); // skip blank line
if (empty.length() > 0)
throw new FileFormatException("missing blank line");
} // if
return new Person(key, name, mail);
} // getPerson()
// Display the array contents.
private void display() {
for (int i = 0; i < n; ++i)
System.out.println(theList[i]);
} // display()
// Read the Person objects from the web page and then start the user
// interface.
private void run() throws IOException {
theList = new Person[1024];
try {
Scanner in = makeScanner();
int index = 0;
Person p = getPerson(in);
while (p != null) {
theList[index++] = p;
p = getPerson(in);
}
n = index;
} catch (IOException e) {
System.err.println("Error reading web page: " + e);
System.exit(1);
// The call to exit may be overkill, but it is nice to return an
// error (nonzero) value to the environment. Since main() does
// nothing after run() returns, simply returning to main() would
// be acceptable also. Perhaps the easiest way to do this is to
// simply move the call to ui() below into the try block. Then if
// an exception is thrown, the UI never executes.
} // catch
// Run the user interface.
ui();
// display();
} // run()
// Loop prompting the user for an integer key. Terminate on a negative
// key. If a record matching the key is found, display the
// record. Otherwise, indicate that no matching record was found.
private void ui() {
int key = getKey();
while (key >= 0) {
Person p = search(key);
if (p == null)
System.out.println("No person matching key "
+ key
+ " found.");
else
System.out.println(p);
key = getKey();
} // while not done
} // ui()
private int getKey() {
System.out.print("\nPlease enter a key: ");
int key = keyboard.nextInt();
return key;
} // getKey()
private Person search(final int key) {
for (int index = 0; index < n; ++index)
if (key == theList[index].getId()) // Is this the right one?
return theList[index];
return null; // apparently the requested object is not present
} // search()
public static void main(String[] args) throws IOException {
ContactList cl = new ContactList();
cl.run();
} // main()
} // class ContactList
The first thing I would do is change your list declaration! (like you said)
change:
private Person[] theList;
to
private LinkedList<Person> theList;
Then use your compiler to print all your compilation errors or look at all the red squiggles produced in your ide.
At each point where there is a compilation error or red squiggle, determine what array operation you are attempting. Then search on this page for the correct operation or sequence of operations that are equivalent. http://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html
http://www.java2s.com/Code/Java/Collections-Data-Structure/Useforeachlooptogothroughelementsinalinkedlist.htm
This is an example of using a for each statement to link through a simple list. You should change your declaration from an array to a linked list and try something similar to the for each in the above example.
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
More reading on the subject if you need a little more background.