Using 2D parallel arrays to store data - java

I am supposed to let up to 16 guests order wine from a menu like this:
The program has to be modular. To place an order, the guest must be shown a list of product types and then variations based on that type. Once the orders are processed I have to show a final report with: total amount made by the winery, most ordered wine product type, and the wine product/variation combo ordered the most times.
I am not sure how to make a method that will search the counter array for the most ordered product type, and then another method that will search the counter array for the most ordered product/variation combo. That is what I need help with.
import javax.swing.JOptionPane;
public class Wine_Taste{
public static void main(String[] args){
String[]wines = {"Riesling", "Chardonnay", "Sauvignon Blanc", "Merlot"};
String[][]wineTypes=
{{"Dry- $4.50", "Off Dry-$4.00", "Sweet- $5.00",},
{"Apple- $6.00", "Lemon-$5.50","Vanilla- $6.00"},
{"Lime-$4.50", "Lemongrass- $6.50","Coconut- $7.00"},
{"Plum- $5.00", "Black Cherry- $7.50","Chocolate- $6.00"}};
}
double[][]prices= {{4.50, 4.00, 5.00},
{6.00, 5.50, 6.00},
{4.50, 6.50, 7.00},
{5.00, 7.50, 6.00}};
int[][]counter ={{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0}};
counter = go(wines,wineTypes,counter,prices);
public static int[][] go(String[] wines, String[][] wineTypes, int[][] counter, double[][] prices){
go2(counter);
double totalCost = 0;
String user;
int x =0;
while (x<=16){
for(int i = 0;i<wines.length;i++){
JOptionPane.showMessageDialog(null,wines[i]);
}
user = JOptionPane.showInputDialog("choose wine 0-3");
int i = Integer.parseInt(user);
for(int j=0;j<wineTypes[i].length;j++){
JOptionPane.showMessageDialog(wineTypes[i][j]);
}
user = JOptionPane.showInputDialog("choose option 0-3");
int j = Integer.parseInt(user);
totalCost += prices[i][j];
counter[i][j]++;
user = JOptionPane.showInputDialog("Order more? y/n");
if (user.equals("y")){
x++;
else{
JOptionPane.showMessageDialog(totalCost);
}
}
}
return counter;
}
}
}

I wouldn't design the program like that. Following some basic object oriented dev principles you can have a wine class with a wine type, price etc, for example:
public class Wine {
String name;
String type;
double price;
public Wine(String name, String type, double price) {
super();
this.name = name;
this.type = type;
this.price = price;
}
//+getters setters
}
Then you can have an order class that keeps the order specific data, like which wine was ordered, the total price etc.
If for any reason you want to keep using the approach of multiple (not easy to manage) arrays then I guess you can create a hashmap where the keys are the wine names and the values the popularity. You can increment by one when a new wine is ordered. You can increment as here:
How to update a value, given a key in a java hashmap?
If for any reason you don't want or can't use this approach then you can create two functions: getPopularProductVarCombo() for the most ordered type per wine, and getMostPopular() for the most popular of all.
To implement getMostPopular you have to find the max value of the array. Here is a good example on how to do this
Print largest number in a 2d array - why do my code print three numbers
To implement getPopularProductVarCombo() then find the max value per line. Any other additional info you might need can be fetched in a similar way.

Related

Java-Selection sorting an array of objects by an int key and displaying in table

I am currently working on a project for school and am really struggling. I am supposed to selection sort a group of Student objects and then display them in selection sort order.
Create an array with the size of 10 and assign student details (Name, BroncoId, age and TotalMarks) to the array. Perform the selection sort to sort the students in descending order based on their total marks.
a. Steps:
i. Create the student list (use Random class in java to generate the age (15-25) and total (0-100))
ii. Print the Student List in a table format
iii. Perform selection sort based on the total marks of the students
The place I am stuck at currently is making the selection sort. I understand how to create the selection sort, but I can't seem to translate it for this implementation.
My selection sort code:
public static Student[] selectionSort(Student[] studentList)
{
for(int i = 0; i <studentList.length-1; i++)
{
int minIndex = studentList[i].getGrades();
int pos = i;
for(int j = i + 1; j < studentList.length-2; j++)
{
if(studentList[j].getGrades() > studentList[minIndex].getGrades())
{
minIndex = studentList[j].getGrades();
pos = j;
}
}
int temp = studentList[pos].getGrades();
studentList[pos] = studentList[i];
int k = studentList[i].getGrades();
k = temp;
}
return studentList;
}
When I run this code, the console returns:
I sought tutoring to hopefully fix this problem, but my tutor gave me a few nonfunctional suggestions. We were both stumped at the end of the session.
My code for printing:
public static void printStudentInfo(Student[] students)
{
System.out.println("Name: AGE: idNumber: Score:");
for(Student student: students)
{
if(student.getName().length() <= 49)
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName(), student.getAge(), student.getID(), student.getGrades() );
else
{
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName().substring(0,48), student.getAge(), student.getID(), student.getGrades() );
System.out.println();
int i = 0;
while(i <= student.getName().length())
{
System.out.printf("%-50s", student.getName().substring(49 +48*i, 97+48*i) );
System.out.println();
i++;
}
}
}
}
As more of an issue out of passion, I sought to make an interesting print method. My problem is, also that I don't really know how to parse and format a string of 155 characters for instance. What do I put in this while lop to accomplish this?
I want the program to output one object name line like:
49 characters
49 chars
…
What ever is left
It probably won't ever go past three lines, but hey, who says I can't give an example like that? What do I put in the header of the while loop to accomplish this?
PS:
Here is the Student class if you need it.
public class Student
{
private String name;
private int age;
private String idNumber;
private int gradePoints;
public Student(String name, int age, String idNumber, int gradePoints)
{
this.name = name;
this.age = age;
this.idNumber = idNumber;
this.gradePoints = gradePoints;
}
public void setName(String name)
{
this.name = name;
}
public void setAge(int age)
{
this.age = age;
}
public void setidNumber(String idNumber)
{
this.idNumber = idNumber;
}
public void setPoints(int gradePoints)
{
this.gradePoints = gradePoints;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String getID()
{
return idNumber;
}
public int getGrades()
{
return gradePoints;
}
Welcome to SO Matthew.
Rather than giving you a solution I thought it might be useful to give you a process for solving the problem yourself.
Good practice in software development is to break your problem down into very small components, make sure each of those work perfectly (through unit testing) and then build your solution from those components.
In line with that practice I suggest you do the following:
list each of the individual steps required to do a selection sort on paper.
Pick the simplest one (e.g. swapping two elements).
Write a unit test that would pass if your swap method worked
run the unit test and verify that it fails
write the simplest code you can to make that test pass
write a new test to cover a more complex scenario that isn't yet supported
keep going until you believe that method works perfectly
move onto the next method
once all the components are working perfectly write the method that calls them all using the same process (i.e. test first then code)
If you follow this process then you will end up with a system that you understand perfectly, works, is maintainable, and that you can refactor. It has another very significant benefit: it means when you come to SO with a question you'll be asking about a specific item that you don't know how to solve rather than a 'why doesn't my code work' question. Specific questions tend to get better and faster responses.
In your case, I would start with methods for swapping items (hint: your code for this doesn't work which you'll discover quickly when you write a unit test) and then move on to finding the smallest item in a sublist. Then a method that uses those two to put the smallest item at the start of a sublist. Finally a method that performs that method for all sublist progressively. Make sure each method is working perfectly, including checking validity of arguments, before you move on to putting them together.

How to Perform Percentage on item list Enum? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm looking for some tip on how to do a percentage thing for my game I want all flowers in a range of 1-98 and white/black flowers 99-100 to make it more rarerity thanks for the help :)
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1 ),
RED_FLOWERS("red", ":red:", "470419583250202644", 1),
RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1),
PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1),
ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1),
BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1),
BLACK_FLOWERS("black", ":black:", "470419706751352842", 1);
private final String displayName;
private final String emoticon;
private int value;
private final String id;
FlowerSuit(String displayName, String emoticon, String id, int value ) {
this.displayName = displayName;
this.emoticon = emoticon;
this.value = value;
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public String getEmoticon() {
return emoticon;
}
public String getId() {
return id;
}
public int getValue() {
// TODO Auto-generated method stub
return value;
}
}
This is how I'd do it, but it can probably be improved, for starters by using Java 8 streams etc.
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1,3),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1,2),
RED_FLOWERS("red", ":red:", "470419583250202644", 1,2),
RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1,2),
PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1,2),
ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1,2),
BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1,2),
BLACK_FLOWERS("black", ":black:", "470419706751352842", 1,1);
private static Random random = new Random();
private final String displayName;
private final String emoticon;
private int value;
private final String id;
private final int freq;
private FlowerSuit(String displayName, String emoticon, String id, int value, int freq ) {
this.displayName = displayName;
this.emoticon = emoticon;
this.value = value;
this.id = id;
this.freq = freq;
}
public String getDisplayName() {return displayName;}
public String getEmoticon() {return emoticon;}
public String getId() {return id;}
public int getValue() {return value;}
/**
* Choose a flower
* white has a 3 in 16 (about a 5:1) chance of being picked
* Black has a 1 in 16 chance, everything else 2/16
* #return
*/
public static FlowerSuit pick() {
//first sum all the chances (currently it's 16)
int sum = 0;
for (FlowerSuit f:FlowerSuit.values()) sum+= f.freq;
//now choose a random number
int r = FlowerSuit.random.nextInt(sum) + 1;
//now find out which flower to pick
sum = 0;
for (FlowerSuit f:FlowerSuit.values()) {
sum += f.freq;
if (r<=sum) return f;
}
//code will never get here
return FlowerSuit.WHITE_FLOWERS;
}
public static void main(final String[] args) throws Exception {
//Test it
Map<FlowerSuit,Integer>count = new HashMap<FlowerSuit,Integer>();
for (int a=0;a<1000000;a++) {
FlowerSuit f = FlowerSuit.pick();
Integer i = (count.get(f)!=null)?count.get(f):new Integer(0);
i = new Integer(i+1);
count.put(f,i);
}
int sum = 0;
for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) sum+=e.getValue();
float f = Float.valueOf(sum);
for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) {
System.out.println(e.getKey() + " was chosen " + ((e.getValue() / f) * 100f) + "% of the time");
}
}
}
gives
BLUE_FLOWERS was chosen 12.4986% of the time
PASTEL_FLOWERS was chosen 12.4707% of the time
WHITE_FLOWERS was chosen 18.7365% of the time
BLACK_FLOWERS was chosen 6.2632003% of the time
ORANGE_FLOWERS was chosen 12.4986% of the time
RED_FLOWERS was chosen 12.5241995% of the time
YELLOW_FLOWERS was chosen 12.501401% of the time
RAINBOW_FLOWERS was chosen 12.5068% of the time
You can use a TreeMap to map all of the integers from 0 to 99 to a particular FlowerSuit. Take advantage of the floorEntry method to choose a FlowerSuit for each number. It might look something like this.
public class FlowerChooser {
private static final NavigableMap<Integer, FlowerSuit> FLOWER_SUITS;
private static final Random RANDOMS = new Random();
public FlowerChooser() {
FLOWER_SUITS = new TreeMap<>();
FLOWER_SUITS.put(0, FlowerSuit.RED_FLOWERS);
FLOWER_SUITS.put(14, FlowerSuit.ORANGE_FLOWERS);
FLOWER_SUITS.put(28, FlowerSuit.YELLOW_FLOWERS);
FLOWER_SUITS.put(42, FlowerSuit.GREEN_FLOWERS);
FLOWER_SUITS.put(56, FlowerSuit.BLUE_FLOWERS);
FLOWER_SUITS.put(70, FlowerSuit.INDIGO_FLOWERS);
FLOWER_SUITS.put(84, FlowerSuit.VIOLET_FLOWERS);
FLOWER_SUITS.put(98, FlowerSuit.WHITE_FLOWERS);
FLOWER_SUITS.put(99, FlowerSuit.BLACK_FLOWERS);
}
public FlowerSuit randomFlowerSuit() {
int index = RANDOMS.nextInt(100);
return FLOWER_SUITS.floorEntry(index).getValue();
}
}
Create just one object of this class, then whenever you want a FlowerSuit, call the randomFlowerSuit method.
The randomFlowerSuit method picks a random number from 0 to 99, then finds an appropriate entry in the map. The floorEntry method chooses an entry whose key is less than or equal to the chosen number. This means that numbers from 0 to 13 get mapped to red, 14 to 27 get mapped to orange, and so on. The only number that gets mapped to white is 98, and the only number that gets mapped to black is 99.
No matter what solution you implement, you want to include a frequency measure in your enum. As an example, you can do something like this:
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1, 1),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1, 20),
// More declarations here
// Add this variable
private final int frequency;
// Do just as you did before in the constructor, but with the frequency
FlowerSuit(String displayName, String emoticon, String id, int value, int frequency){
this.frequency = frequency;
// More assignments here
}
public int getFrequency(){
return frequency;
}
// More getters here
}
This addition is critical, and no matter what method you use to weight flower selection, you will want this addition to your FlowerSuit enum.
Now, we can explore a few different ways to perform this selection.
Note 1: I use ThreadLocalRandom for random numbers in a range, which is from java.util.concurrent.ThreadLocalRandom.
Note 2: For each of these, make a single instance of FlowerPicker, and use the pickFlower() method to pick the next flower. This avoid running costly setup code over and over.
Method 1: Bag of Flowers
This method is probably the easiest to implement. It entails creating a list of enums where each is represented frequency times, and then selecting a random entry from this list. It is similar to throwing a bunch of flowers in a bag, shaking it, and then reaching your hand in and grabbing the first flower you touch. Here's the implementation:
public class FlowerPicker(){
private ArrayList<FlowerSuit> bag;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
// You can use an array here or an array list with a defined length if you know the total of the frequencies
bag = new ArrayList<FlowerSuit>();
// Add each flower from options frequency times
for (FlowerSuit flower : options)
for (int i=0; i<flower.getFrequency(); i++)
bag.add(flower);
}
public FlowerBag pickFlower(){
// Now, select a random flower from this list
int randomIndex = ThreadLocalRandom.current().nextInt(0, bag.size());
return bag.get(randomIndex);
}
}
This method has the advantage of being simple enough to understand very easily. However, it can be inefficient if your frequencies are extremely specific (like if you want a rainbow flower to be returned 499,999,999 times out of 1,000,000,000). Let's move on to the next method.
Note 1: You could make this better by reducing the fractions representing the frequency of being chosen, but I'll leave this to you.
Note 2: You could also make this slightly better by storing identification numbers, not FlowerSuit objects in the bag list.
Method 2: Navigable Map
This method is a little bit more difficult. It uses a [NavigableMap][1], which is an implementation of [TreeMap][2]. This method is fairly similar to the Bag of Flowers method, but it is a little bit more efficient. Put simply, it uses the TreeMap to give each FlowerSuit a range of numbers that can be selected to return that FlowerSuit. Here's a full example:
public class FlowerPicker(){
private NavigableMap<Double, FlowerSuit> map;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
map = new TreeMap<Double, FlowerSuit>();
int runningTotal = 0;
// Add each flower with the proper range
for (FlowerSuit flower : options){
runningTotal += flower.getFrequency();
map.put(runningTotal, flower);
}
}
public FlowerBag pickFlower(){
// Now, select a random number and get the flower with this number in its range
int randomRange = ThreadLocalRandom.current().nextInt(0, bag.size());
return map.higherEntry(randomRange).getValue();
}
}
This is a solid method, and it scales well for very specific frequencies. If you have a bunch of different types of flowers, it will be slightly worse, but this method is still a good option at large scales. There's one more option though.
Method 3: Enumerated Distribution
This method is really nice because you barely have to do anything. However, it uses [EnumeratedDistribution][3] from Apache Commons. Enumerated Distribution requires a list of pairs of objects and weights. Anyway, lets jump into it:
public class FlowerPicker(){
private EnumeratedDistribution distribution;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
List<Pair<FlowerSuit, Double>> weights = new List<Pair<FlowerSuit, Double>>();
// Add each flower and weight to the list
for (FlowerSuit flower : options){
weights.add(new Pair(flower, flower.getFrequency()));
// Construct the actual distribution
distribution = new EnumeratedDistribution(weights);
}
public FlowerBag pickFlower(){
// Now, sample the distribution
return distribution.sample();
}
}
This is my favorite method, simply because so much of it is done for you. Many problems like this have been solved, so why not use solutions that always exist? However, there is some value to writing the solution yourself.
In conclusion, each of these methods are perfectly fine to use at your scale, but I would recommend the second or third method.

java: confusing instructions, shopping cart program

My teacher gave me confusing instructions on this coding assignment. If you guys could help elaborate or give me tips, I'll provide what I have.
First of all the program is where I have to make 2 classes that will work with a big class to produce a shopping list where you can edit how much of each item you want. Have to take the name of an item, how many times its purchased, and how much each one costs.
I finished my first class, I'll post the entire coding and rules for the coding at the bottom of this question.
Okay so here's what I have. I'll go step by step.
Rule 1: A field private Purchase[] as an array of purchases.
Another int field that tracks how many purchases have actually been made
So I made this:
private int Purchase[];
private int purchaseCount;
Rule 2: Negative values do not make sense, so just reset those to zero if provided by user
Okay so in the first program I had to do the same thing, but I'm confused how to do it now.
I implemented the "reset to zero" in the modifiers, but now my teacher is not asking for modifiers. Am I supposed to put them anyway? I know I just have to put an "if blahblahblah < 0, then blahblahblah = 0" thing, but how do I go about that?
Rule 3: Accessor .length() method that returns your int field for how many purchases
public int Purchase(){
return ;
}
I guess this is about all I know for that. I know I have to return something, not sure how to use length though. And I think there's a parameter.
Final Rule 4: Accessor .get(int) for the Purchase array, which needs a parameter that will index the array. So get(0) returns the first element (a Purchase object) of the array.
I think I understand this, but since I don't know how to do the last step, I haven't tried this yet. ".get(int)" what? So an accessor where I perform a .get(int) inside it? I don't know much about accessors, this is why I need this help. The rest of the program seems pretty simple for me, but this initial stuff confuses me. Thanks.
Rules for already completed class:
Three fields, a String for name of the purchase, int for units purchased, and a double for cost per unit.
• Standard accessors and modifier methods for each field.
• Negative values are not allowed, so change those to zero in all cases.
• Constructor to initialize these three fields (String, int, double) in that order.
• Constructor overload, (String, double) assumes the int quantity is zero.
• Default constructor that assumes name is “” and numbers are zero, must call the three argument constructor.
• A getCost method that is simply the number of units purchased times unit price.
• A toString method return a String with the item name followed by the unit price in parentheses
Completed program:
public class Purchase {
private String purchase;
private int unitsPurchased;
private double costPerUnit;
// Accessors
public String purchase() {
return purchase;
}
public int unitsPurchased() {
return unitsPurchased;
}
public double costPerUnit() {
return costPerUnit;
}
// Modifiers
public void setPurchase(String purchase) {
this.purchase = purchase;
}
public void setunitsPurchased(int unitsPurchased) {
if (unitsPurchased < 0) {
unitsPurchased = 0;
}
this.unitsPurchased = unitsPurchased;
}
public void setCostPerUnit(double costPerUnit) {
if (costPerUnit < 0) {
costPerUnit = 0;
}
this.costPerUnit = costPerUnit;
}
//constructors
public Purchase() {
this("", 0, 0);
}
public Purchase(String initialPurchase, double initialCostPerUnit) {
this.purchase = initialPurchase;
this.unitsPurchased = 0;
this.costPerUnit = initialCostPerUnit;
}
public Purchase(String initialPurchase, int initialUnitsPurchased, double initialCostPerUnit) {
this.purchase = initialPurchase;
this.unitsPurchased = initialUnitsPurchased;
this.costPerUnit = initialCostPerUnit;
}
//end of everything I am sure about
//beginning of unsurety
public static double getCost(String purchase, int unitsPurchased, double costPerUnit) {
return unitsPurchased * costPerUnit;
}
public static String toString(String purchase, int unitsPurchased, double costPerUnit){
return purchase + costPerUnit;
}
}
Okay, so first rule 1 the code should look like:
private Purchase[] purchases;
private int purchaseCount;
Remember, in this case since you've already defined Purchase in your other java file, you're using it as a datatype, not as an identifier.
For rule 2, you're going to want that if statement in the access methods for purchaseCount as well as in the constructor.
Rule 3 is extremely vague...but my best guess is your teacher wants you to define a length method for that class, so that when you call say purchases.length() it returns the purchase count.
Again, rule 4 is vague, but my best guess is you need to define a get method for that class that just returns a value from your private purchases array using a given index.
Something like this:
public Purchase get(int index) {
return purchases[index]
}
I hope this helps and good luck!!

Find Range in which value lies in Java

Suppose, I have an unsorted array of ranges.
For e.g
class CreditRange{
long credits;
int id;
}
Now I want to find, given credit count value belongs to which one of the CreditRange.
Possible Set<CreditRange> of values can be
CreditRange :{id:1,credits:0}
CreditRange :{id:2,credits:100}
CreditRange :{id:3,credits:500}
CreditRange :{id:4,credits:250}
Case 1 : Now when user enters Credits = 50, this range comparator should give
answer as
CreditRange :{id:1,credits:0}
Case 2 : Now when user enters Credits = 300, this range comparator should give
answer as
CreditRange :{id:4,credits:250}
Case 3 : Now when user enters Credits = 600, this range comparator should give
answer as
CreditRange :{id:3,credits:500}
We can assume the ranges array takes ~1M and fits the memory. I am looking for an easy algorithm, which uses only standard JDK collections without any 3d-party libraries and special data structures, but works reasonably fast.
What would you suggest?
I guess, it's not the range you are talking about. Rather you want the largest element that is less than your passed element.
You can follow the below steps to solve the problem:
First implement a Comparator for your class, which compares on the basis of credits
Then, use a TreeSet, passing an instance of that comparator to it's constructor. It will sort the item inside it, as per the comparator.
Then use TreeSet#floor(E) method to get the greatest element which is less than E, as per the comparator. Of course, you have to create an object of CreditRange to search. You can't just search for 300.
Demo code:
NavigableSet<Integer> set = new TreeSet<>();
set.add(0); set.add(100);
set.add(250); set.add(500);
System.out.println(set.floor(50)); // 0
System.out.println(set.floor(300)); // 250
And please rename your class. It is not depicting the range in any manner. It should perhaps be better named as CreditBound as specified by Jon Skeet in comments.
As mentioned by Rohit, one easy method is to use TreeSet floor (another is to implement a a modified variant of Binary search. this is a more complete answer:
package test;
import java.util.TreeSet;
class CreditRange implements Comparable<CreditRange> {
long credits;
int id;
public CreditRange(int id, long credits) {
this.id = id;
this.credits = credits;
}
public CreditRange(long credits) {
this.id = -1;
this.credits = credits;
}
#Override
public int compareTo(CreditRange o) {
return credits < o.credits ? -1 : credits > o.credits ? 1 : 0;
}
#Override
public String toString() {
return "id:" + id + ", credits:" + credits;
}
}
public class Test {
public static void main(String[] args) {
TreeSet<CreditRange> set = new TreeSet<>();
set.add(new CreditRange(1, 0));
set.add(new CreditRange(2, 100));
set.add(new CreditRange(3, 500));
set.add(new CreditRange(4, 250));
System.out.println(set.floor(new CreditRange(50)));
System.out.println(set.floor(new CreditRange(300)));
System.out.println(set.floor(new CreditRange(600)));
}
}

How can I avoid using a lot of variables?

I would like to create a simple program that would output the atomic mass of any element entered. I am taking a Java course that I recently started so I don't know how to avoid using over 100 variables each with the elements atomic mass.
Also how could I get a if statement to use the name input from the user (which I know how to store in a string) and match it with one of the elements, in order to output the element's mass (corresponding to method used to store the multiple elements).
How can I condense this example code:
int carbon = 12;
int oxygen = 16;
int hydrogen = 1;
int sulfur = 32;
etc....
Sounds like your first step is to learn about the Map data structure. You can use it to associate the string names to integer values and then look them back up later.
Map<String, Integer> elements = new HashMap<String, Integer>();
elements.put("CARBON", 12);
elements.put("OXYGEN", 16);
//etc
Then if you have some input you can look up the number.
String userInput = scanner.next(); // or however you're getting input
Integer atomicWeight = elements.get(userInput.toUpper());
if (atomicWeight == null) //print element not found etc
Then once you have the program down and working you can learn about whatever technology is appropriate for loading the reference data from outside of the source code, whether that's a file or a database or a webservice or whatever.
I'd likely define an enum if confronted with this problem.
public enum Elements
{
HYDROGEN(1),
...
UNOBTANIUM(666);
public final int atomicWeight;
Elements(int atomicWeight)
{
this.atomicWeight = atomicWeight;
}
}
then to get the right element it's
String name = ...// from user input
Elements e = Elements.valueOf(name.toUpperCase());
I'd recommend using an enum as some have suggested, though i'd do it a little different. Maps have lots of overhead, and since your data is not dynamic it's not a great fit. Atomic mass should be a decimal value (double or BigDecimal depending on what you're using it for), not an int
public enum AtomicElement {
HYDROGEN(1.00794),
HELIUM(4.002602),
...;
private double atomicMass;
private AtomicElement (double atomicMass) {
this.atomicMass = atomicMass;
}
public int getAtomicNumber() {
return ordinal();
}
public double getAtomicMass() {
return atomicMass;
}
public static AtomicElement forAtomicNumber(int atomicNumber) {
return AtomicElement.values()[atomicNumber];
}
public static AtomicElement forElementName(String elementName) {
return AtomicElement.valueOf(elementName);
}
}
Then you can search by atomic number or element name
AtomicElement.forAtomicNumber(2);
AtomicElement.forElementName("CARBON");
This does however assume you're going to represent the entire periodic table with no gaps in the data, since it's using the ordinal() value as the atomic number. If you want gaps, you'll have to have an int field for the atomic number and your "forAtomicNumber" function will have to cycle through the "values()" to find the one with the given number.
You could even extend this if you wanted to include known isotopes, etc... if your requirements dictate that.
Because the atomic mass of the elements is not going to change at any point in your app, you should define them as final:
public class AtomicMass {
public static final int CARBON = 12;
public static final int OXYGEN = 16;
...
}
...or, you could use an enum:
public static enum Element {
carbon(12),
oxygen(16),
hydrogen(1),
sulfur(32);
private int atomicMass;
private Element( int mass ) {
this.atomicMass = mass;
}
}
If you order your elements sequentially (and add an UNKNOWN for 0) you wouldn't even need to explicitly provide the mass.
I like to group related data into arrays or arrayLists.
String[] elements = new String[# of elements in table];
Based on the position of the element you can have the atomic number.
Then I would loop through them to find any element or fill the array.
You can look into Java Scanner class to get input from user.
Create a class called Element that contains attributes like name, atomic number, etc. Each element will correspond to an instance of Element. You can then put all the Elementss in several maps, keyed by name, atomic number, etc. Use a factory class to instantiate and initialize the maps, and provide lookup methods.
If I understand you correctly you just want to only have 1 variable to store all the elements and their masses in which case I would recommend a HashMap. It will not really save on code lines but will let you do number 2 pretty easily. HashMaps store a set of key-value pairs and you can get the value if you have the key so this would create the list:
//Declare a new hashmap and initialize it
HashMap<String, Integer> elements = new HashMap<>();
//Add element information
elements.put("CARBON", 12);
elements.put("OXYGEN", 16);
elements.put("HYDROGEN", 1);
elements.put("SULFUR", 32);
Then for example to get user input from a dialog box and print the result to command line you do something like this:
//Collect user input and convert it to all upper case (in real life you would validate this)
String input = JOptionPane.showInputDialog(null, "Please enter an element name").toUpperCase();
//If element name exists in hashmap print its atomic weight
if(elements.containsKey(input.toUpperCase())){
System.out.println("Atomic Weight: " + elements.get(input));
}
Store your data in a file
Element, Weight
oxygen = 16
carbon, 12
.
.
.
Pseudocode:
//Read data file into a `Map<String, int>`
//Get user input
//Access map
//Output

Categories