I'm developing a quiz app and I want to find an efficient way to save user's answers.
Each quiz has 30 questions and all I need to save is:
questionNumber, questionId and answerId and either the answer is correct or not.
I thought an array will be a good solution. Example:
Each row represents a question (questionNumber). The first column represents the questionId and the second answerId. The third column will contain either 0 (incorrect) or 1 (correct).
The third column (correct) is needed to sum the number of correct answers (it's faster to sum the third column instead of checking each answer any time).
This isn't a SQL table - this info is temporary and will be destroyed as soon as the user finishes the quiz.
I want to know if you have any other solutions, maybe better.
Thank you!
Why not a class?
class Answer
{
private int questionID;
private int answerID;
private boolean correct;
public Answer(int questionID, int answerID, boolean correct)
{
this.questionID = questionID;
this.answerID = answerID;
this.correct = correct;
}
}
And an ArrayList
List<Answer> answers = new ArrayList<Answer>();
Then use
Answer answer = new Answer(1, 2, true);
answers.add(answer);
With an Array you will need to fix the array size every time you add a question with an ArrayList you can add as much questions as you want without care about the array size.
Anyway, if you questions will be always 30 you can create an Array too without problems.
About performances, well i don't see problems about speed/memory.
Related
Hello to anyone reading this, I've spent a couple hours now trying to figure out the root of a problem I've been having with an array list in a JavaFX trivia program I'm writing. I've finally narrowed down where the issue is, I just can't figure out what's causing it. Basically, I have a while loop that keeps reading lines of code until it reaches the end, and that works. At the end of each loop, I add the data I read to an ArrayList in the form of an object, that holds the data I read. It works, as when I print one of the parameters from the object at each index in the array list, it works. However, the moment I step outside of the while loop, every single index of the ArrayList holds the exact same data, and it is always the final question I saved for.
Here is the code:
while ((line = questionStream.readLine()) != null) {
// The question
String inquiry = line;
// The first possible response
line = questionStream.readLine();
String[] responses = new String[4];
responses[0] = line;
// The second possible response
line = questionStream.readLine();
responses[1] = line;
// The third possible response
line = questionStream.readLine();
responses[2] = line;
// The fourth possible response
line = questionStream.readLine();
responses[3] = line;
// The fact to display once the question has been answered
line = questionStream.readLine();
String fact = line;
// Space in between questions
questionStream.readLine();
// Adding the question
questions.add(new Question(inquiry, responses, fact));
Console.print(questions.get(temp).getInquiry());
temp++;
}
questionStream.close();
for (int i = 0; i < questions.size(); i++) {
Console.print(questions.get(i).getInquiry());
}
And the output is as follows:
How many countries border France?
What sea creature has 3 hearts?
The Simpsons is the longest running tv series. What is the name of the janitor?
What was the product of the first ever TV advertisement?
What TV series features a reference to or a picture of Superman in almost every episode?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
How many castaways were on Gilligans Island?
So I'm really confused how the ArrayList holds all of the proper data perfectly, right until it exits the while loop, where it then only ever holds whatever the final question is in the text file.
Thanks for the help!
The problem is that you are not using instance variables in your Question class but class variables. That means your Question class should look like this in order to work as expected:
package trivia.questions;
public class Question {
// Data fields, don't use static!
private String inquiry;
private String[] answers;
private String fact;
private String correctAnswer;
...
/**
* Overloaded constructor
*
* #param inquiry the question
* #param answers the answers
* #param fact the cool fact for the correct answer
*/
public Question(String inquiry, String[] answers, String fact) {
this.inquiry = inquiry;
this.answers = answers;
this.fact = fact;
}
Using static for the variables will make that this variable is shared between all instance of your Question variable.
In each iteration you print out the current state which seem to be okay but after you finished you print out multiple time the same state which is shared between your different copies of class Question.
This is one major concept in object oriented programing in Java.
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 4 years ago.
So I'm a scrub at java, just started learning the language at a university course.
While trying to compare values of variables linked to objects to inserted values to make sure that there are no duplicates, I ran into an issue. It appears as if the objects are "lagging behind" in the lack of a better expression. See the commenting of the code for a better explanation.
The problem only appears if you add like 2 or more separate weapons and then try to re-add a weapon with the same name, it allows you to do so. If you add just one one weapon and then try to re-add it it says nope and the code works as intended.
So yeah, when I call the method printHeroInfo I still see that I can end up with several weapons with the same name. There is also another class called superWeapon, and if you think the code in there is relevant to this issue then let me know and I'll post that in a commment or something.
Thanks in advance for helping me with the head scratching.
import java.util.ArrayList;
public class superHero{
private ArrayList<superWeapon> superWeaponList;
private String superHeroName;
private String superHeroInfo;
public superHero(String superHeroName, String superHeroInfo){
this.superHeroName=superHeroName;
this.superHeroInfo=superHeroInfo;
superWeaponList=new ArrayList<superWeapon>();
}
public void addSuperWeapon(String superWeaponName, int superWeaponCharges){
superWeapon Obj = new superWeapon(superWeaponName, superWeaponCharges); // Making an object of the superWeapon class.
int size=superWeaponList.size(); // Gets the size of the array superWeaponList.
if(size==0){ /* If the size of the arary is zero, that means there are no weapons in it currently.
For that reason we don't need the for-loop we otherwise would need to compare the name of the weapon
we are trying to add against the pre-existing names of weapons in the array. */
superWeaponList.add(Obj);
System.out.println("The Superweapon"+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}
else{ /* If the size of the array is NOT zero, we need to compare the name of the weapon we are trying to add
against the weapons already existing in the array. This we do with the following for loop. */
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
String temp_name = temp_obj.getName();
System.out.println(temp_name); /* Why does the name lag behind one entry?
On the second entry it also shows the first entry. On the third entry it shows the second
entry and so on... The first place in an arraylist should be index=0,
so the for-loop starting at 0 should also be correct, right?
I just added this print to see what the current value for getName()
would end up returning. This is how I found the bug/error. */
if(temp_name!=superWeaponName){ // If the name doens't match then we add a new superweapon.
superWeaponList.add(Obj);
System.out.println("The superweapon "+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}else{ // If the names match however, we don't add the new weapon we were trying to add.
System.out.println("There already is a superweapon with the name "+superWeaponName+
" registered for the superhero "+superHeroName);
}
}
}
}
public void printHeroInfo(){
System.out.println(superHeroName);
System.out.println(superHeroInfo);
int size=superWeaponList.size();
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
System.out.println(superHeroName+" has the superweapon "+temp_obj.getName()+" with "+temp_obj.getCharges()+" charges.");
}
}
}
Although it can be improved a lot with using Set instead of list, but I will just point out the error in assumption you are making in comparing Strings...
if(temp_name!=superWeaponName) //incorret
if(!temp_name.equals(superWeaponName)) //correct
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have data type of the following format:
Popularity:xx
Name:xx
Author:xx
Sales:xx
Date Published: xx
I am free to choose whatever way I can store my data in.
I will need to perform some queries on the data, for example
What are the top 'N' Books for the year 'M'
What are the average sales of the top 'N' songs for author 'X'?
It should be kept in mind that further queries may be added.
What will be the different ways to represent the data to perform the queries (in Java)? What will be the merits?
Note: (Not looking for a DB solution)
JDK comes bundled with Java DB and seems perfectly fine for your use case.
Edit: Sorry I misread the question as a dB solution because it seems you need it. That said you should look for a DB solution where you just query your books from.
If you actually do want to perform queries on data-structures in memory you can use Apache Commons Collections which support filtering.
If you do want to use a data-structure like a Vector which seems like a solution, you need to build indexes to improve performance. Then lookup in the indices and get the book needed. If you know which searches are necessary you can group chosen indexes and create a block to easily search. Essentially creating your own cube data-structure. Could be a nice project.
Arraylist of a class. Create a class with those variables as, well, class variables, then instantiate an Arraylist of said object. Then you can perform searches based on the values of certain variables. For example:
//replace "ClassName" with the name of the class
ArrayList<"ClassName"> array = new ArrayList<"ClassName">();
ArrayList<"ClassName"> results = new ArrayList<"ClassName">();
for("ClassName" obj:array)
{
if(obj.getAuthor().equals("Author Name"))
{
results.add(obj);
}
}
There are many ways to sort the results, including using Collections.sort(); which seems to be the best way to go about it.
Sort ArrayList of custom Objects by property
EDIT: I went ahead and gave you an example based on the specific case you outlined in the comments. This should help you out a lot. As stated before, I had a similar issue for a lab in University, and this was a way I did it.
You could use a Bean to wrap your data:
public class Record {
int popularity;
String name;
String author;
int sales;
int yearPublished;
public Record(int popularity, String name, String author, int sales, int yearPublished) {
super();
this.popularity = popularity;
this.name = name;
this.author = author;
this.sales = sales;
this.yearPublished = yearPublished;
}
//getter and setter...
public String toString(){
return name;
}
And this is a typical usage querying with java8:
Record Record1 = new Record(10,"Record 1 Title","Author 1 Record",10,1990);
Record Record2 = new Record(100,"Record 2 Title","Author 2 Record",100,2010);
Record Record3 = new Record(140,"Record 3 Title","Author 3 Record",120,2000);
Record Record4 = new Record(310,"Record 4 Title","Author 1 Record",130,2010);
Record Record5 = new Record(110,"Record 5 Title","Author 5 Record",140,1987);
Record Record6 = new Record(160,"Record 6 Title","Author 1 Record",15,2010);
Record Record7 = new Record(107,"Record 7 Title","Author 1 Record",4,1980);
Record Record8 = new Record(1440,"Record 8 Title","Author 8 Record",1220,1970);
Record Record9 = new Record(1120,"Record 9 Title","Author 9 Record",1123,2010);
List<Record> Records = Arrays.asList(Record1,Record2,Record3,Record4,Record5,Record6,Record7,Record8,Record9);
//top 2 record of year 2010
int m = 2;
int year = 2010;
System.out.println(Arrays.toString(Records.stream().filter(s -> s.getYearPublished() == year).sorted((r1, r2) -> Integer.compare(r2.popularity, r1.popularity)).limit(m).toArray()));
//average top 2 record of Author 1 Record
String author= "Author 1 Record";
int n = 2;
System.out.println(Records.stream().filter(s -> author.equals(s.getAuthor())).sorted((r1, r2) -> Integer.compare(r2.popularity, r1.popularity)).limit(n).mapToInt(Record::getSales).average().getAsDouble());
This prints:
[Record 9 Title, Record 4 Title]
72.5
Having a collection of objects you can use stream api to collect/filter/reduce your results. There is not so much to it.
The main problem is to not load all of the objects to memory and to be able to retrieve them from whatever store efficiently by using indexes, reverse-indexes.
One of the frameworks which came to my mind is Apache spark
this is my first question here ever, and I would appreciate if you can help me.
Since the code I have is way too large to post here, I'll try to describe what my problem is in short.
So, I have made TimeSeries array within my class and array list from where I get values for time series:
private TimeSeries[] seriesArray = new TimeSeries[10];
ArrayList<TempClass> valuesFromArrayList = new ArrayList<>();
I need to make TimeSeries array, because I want to be able to show multiple timeseries graphs. Using only one TimeSeries and addOrUpdate method isn't what I want because then values get mixed when I create more graphs. So, I add values like this:
for(int i = 0; i < valuesFromArrayList.size(); i++)
{
TempClass obj = (TempClass) valuesFromArrayList.get(i);
int timeStamp = obj.getTimeStamp();
int hrsDiff;
int minsDiff;
int secsDiff;
hrsDiff = timeStamp / 3600;
timeStamp = timeStamp - hrsDiff * 3600;
minsDiff = timeStamp / 60;
timeStamp = timeStamp - minsDiff * 60;
secsDiff = timeStamp;
seriesArray[Integer.parseInt(comboBoxValue) - 1].add(new Second(secsDiff, minsDiff, hrsDiff, day, month, year), Math.abs(obj.getValue()));
}
What this part of code does is that it reads values and timestamps from ArrayList I created. There is comboBox where user can choose which timeSeries array index will be in graph. So, if user chooses value 9 from comboBox, timeSeries from index 8 will be chosen and plotted on graph. TimeStamp is simply number of seconds that passed since 00:00:00 at day when values were taken.
TempClass is defined as:
class TempClass
{
private int timeStamp;
private double value;
public TempClass(int a, double b)
{
timeStamp = a;
value = b;
}
public int getTimeStamp()
{
return timeStamp;
}
public double getValue()
{
return value;
}
public void setValue(double val)
{
value = val;
}
}
The problem I have is that when I try to make second (2nd) graph, that is another index of TimeSeries array, I get message:
You are attempting to add an observation for the time period Thu Apr 30 00:00:00 CEST 2015 but the series already contains an observation for that time period. Duplicates are not permitted. Try using the addOrUpdate() method.
I don't want to use addOrUpdate method, I need add method. Values in ArrayList I use to put values into timeSeries are fine, I am 300% sure. I already checked input from comboBox value and it gives correct values.
I have no explanation other that for some reason, even if array index is changed, data I want to write into the series goes to the old series (that is, to the series at the old index). In other words, it seems like even if I change index of array, it keeps writing into the old array index!
It's like equivalent to this (I know this sounds crazy but that is basically what I am getting):
int[] array = new int[5];
array[0] = 1;
array[1] = 2;
System.out.println(array[0]);
And the output I get is
2
This is something I have never heard of before, and I have code similar to this I wrote here in two other places, and in that two places it goes just fine, but in this third place I keep getting that exception.
Is this some kind of bug in JVM?
Does somebody know what this could be?
I don't know too much about TimeSeries, but after skimming the docs about it it says:
"The time series will ensure that (a) all data items have the same
type of period (for example, Day) and (b) that each period appears at
most one time in the series."
Link to Docs
I'm guessing the error is pretty straight forward or a misuse of TimeSeries. It looks like you are simply adding a duplicate date and that the constraints of TimeSeries don't allow that.
You may wish to consider writing a custom class that has the functionality you want. Yet again, I don't know much about TimeSeries, but I hope this helped a little.
Your for loop will always overwrite the value with an index of 0 on seriesArray.
What I mean is, the first time it will write to [0]
The second it will write to [0] then [1]
Is this intended?
I have not looked at the docs too much, but the message says 'the series already contains an observation for that time period.' I think that loop is not doing what you want it to do.
I'm implementing a JTable, where an user can define the TimeTable.
Every subject has a number of credits, and I have to count the sum of all credits in a week. Obviously, for do that it's necessary to count one time all duplicate subject(I would not count two time the credits of the same subject).
For example, if the JTable is
I would like to get the value Math,English,Science, Philosophy, Art only ONE time. I've tried to do this with the follower method:
private void getOnce (String[] dailyLessons)
{
Set<String> weekSubjects = new HashSet<String>();
int weeklyCredits=0;
//dailylessons is a String[] that contains the lessons of the day
Collections.addAll(weekSubjects, dailyLessons);
//String[] week would contain every subject only one time
String [] week = weekSubjects.toArray(new String[0]);
//for all the subject I get its credits
for (int i=0; i<week.length; i++)
{
if (!week[i].equals("no"))
{
String [] credits= week[i].getCredits;
weeklyCredits += credits;
}
}
}
But it does not work. Could you explain me why? A correct version of my code will be very appreciated.
But it does not work. Could you explain me why?
read Oracle tutorial How to use Tables
all data for JTables view are stores in (Creating a Table Model) XxxTableModel
if isn't there any definition for XxxTableModel then DefaultTableModel is used
A correct version of my code will be very appreciated.
good one