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
Related
ArrayList<Integer> companiesId = new ArrayList<>();
int numberOfCompanies = 10; // Just for example
...
float profit;
Scanner input = new Scanner(System.in);
for(int i = 0; i < numberOfCompanies; i++) {
int companyId = input.nextInt();
if (!companiesId.contains(companyId)) {
companiesId.add(companyId);
}
if (companiesId.get(i) == 1) {
profit = 1000;
} else if (companiesId.get(i) == 2) {
profit = 2000;
}
}
Now I want to print all the companyIds from the ArrayList with the profit entered for each id, but I don't know how to do it with the ArrayList.
It should be:
1 1000
2 2000
...
You cannot do what you ask because part of the information you need to print (profit) is lost. What you need to do first is to create a class that holds a company ID and the profits. With the new version of Java, you can create a record that will hold such information. A Java Record is nothing more than a POJO that is identified with that new keyword (record) and does not require you to create all the boilerplate code. Your record class will look something like this:
public record CompanyRecord(int companyID, float profit) {
}
You don't even need to override toString(). That is, unless you want to print the contents of the record in a different way than the default. Then, you will need to create a list of CompanyRecord objects:
ArrayList<CompanyRecord> companies = new ArrayList<>();
Then, you can do whatever you need. For example, I created this simple demo that create a list of 10 company records and uses the loop counter to set the company ID and as a multiplier for the profits. Lastly, it prints out the record to the console.
public class CompanyRecordDemo {
public static void main(String[] args) {
ArrayList<CompanyRecord> companies = new ArrayList<>();
float profit = 1000.0f;
for (int i = 1; i <= 10; i++) {
CompanyRecord rec = new CompanyRecord(i, profit * i);
companies.add(rec);
System.out.println(rec);
}
// do whatever you need with the list...
}
}
The output of this small program is:
CompanyRecord[companyID=1, profit=1000.0]
CompanyRecord[companyID=2, profit=2000.0]
CompanyRecord[companyID=3, profit=3000.0]
CompanyRecord[companyID=4, profit=4000.0]
CompanyRecord[companyID=5, profit=5000.0]
CompanyRecord[companyID=6, profit=6000.0]
CompanyRecord[companyID=7, profit=7000.0]
CompanyRecord[companyID=8, profit=8000.0]
CompanyRecord[companyID=9, profit=9000.0]
CompanyRecord[companyID=10, profit=10000.0]
This is probably the simplest way to accomplish what you need. You will need to use Java 14 or later to make use of Java Records, but I recommend you use the latest version.
UPDATE: One important thing to note is that Java records are immutable. So, they have no setters (mutator methods). You will have to set the values through the constructor and values cannot be changed afterwards. You can access (get) the property values by calling a method that has the same name as the field. For example, the getter method for profit is profit(). For example rec.profit().
I'm trying to understand Array Object, and what I want to do is call my array in every class I have.
this is my code:
projectProva.java
public class ProjecteProva {
Scanner sc = new Scanner(System.in);
private final int maxContador = 4;
private final DadeArr LlistaUsuari[] = new DadeArr[maxContador];
int ContadorActual;
}
DadeArr.java
public class DadeArr {
private String nomUsuari;
private String cognomUsuari;
public DadeArr(String nU, String nC){
nomUsuari = nU;
cognomUsuari = nC;
}
Right now I'm working in projectProva.java , I have some method that saves into array a data input with scanner.
Here is an example of one of my method:
public int inserir(int aContadorActual){
ContadorActual = 1;
for (int i=1;i<=ContadorActual;++i){
System.out.println("Introdueix el nom del usuari: ");
String nU = sc.nextLine();
//sd.setNomUsuari(Name);
System.out.println("Introdueix el teu cognom : ");
String nI = sc.nextLine();
LlistaUsuari[ContadorActual] = new DadeArr(nU,nI);
System.out.println("El teu usuari s'ha creat satisfactoriament");
}
ContadorActual++;
return ContadorActual;
}
This method asks user his name and surname and saves it in array LlistaUsuari.
Then, I want to use this array(with the data in) in another .java file from the same package, but i don't know how to properly call the array.
I just started to learn this type of array, and i want to understand it.
After solving this , im looking forward to take all array info and send it to a data base or text file.
If I can't proceed with it i will switch to Array 2D.
Plus, I'm wondering if this type of Array ( array object ) is very usefull or not.
Thanks.
I also made this question at https://www.reddit.com/r/javahelp/comments/dsyu4b/array_object/?
You have multiple gotchas in your code.
1. you should always iterate an array from index 0 (unless you have special needs or you are programming in a language like Python where arrays start from 0)
2. You should set the condition in the loop to be less than the exact length of the array. So in your case it will be i < LlistaUsuari.length. You are getting a null because you are only filling up index #1 of the array.
All you need is a public getter method for the array that you want to access.
Something like:
public DadeArr[] getLlistaUsuari() {
return this.LlistaUsuari;
}
And that should do it.
In other classes, create an instance of ProjecteProva (lets's call it pPI) and to get the array there, simply do pPI.getLlistaUsuari() and you'll have it,
I've been working on a problem:
"Design a program that asks the user for a series of names (in no particular order). After the final person’s name has been entered, the program should display the name that is first alphabetically and the name that is last alphabetically.
For example, if the user enters the names Kristin, Joel, Adam, Beth, Zeb, and Chris, the program would display Adam and Zeb."
I have a function called getString, which returns a valid string input; and a module called displayResults, which displays the first name alphabetically, and last name alphabetically. I also use "q" as a sentinel value to exit the while loop.
However, I am running into a problem where if I enter in names such as: "bob", "david", "alex", and "charlie", it will display the first name correctly as "alex", but will display the last name incorrectly as "charlie" instead of "david". I've tried looking through my code for an error, but wasn't able to locate where it's messing up. Any help is appreciated.
name = getString("Please enter a name, or input q to exit.");
if(!name.equals("q")) {
low = name;
high = name;
}
while(!name.equals("q")) {
int x;
x = name.compareToIgnoreCase(low);
if(x == -1){
low = name;
}
x = name.compareToIgnoreCase(high);
if(x == 1) {
high = name;
}
name = getString("Please enter another name, or input q to exit.");
}
displayResults(low, high);
The Java API documentation only states that compareToIgnoreCase() "Returns:
a negative integer, zero, or a positive integer". Since you are comparing x to 1 and -1 respectively it is possible you are actually receiving another value back and therefore the true "high" is not being detected.
Another possibility is that there may be invisible characters (like space or return) in your input. When I ran " david".compareToIgnoreCase("charlie") on my machine here it returned -67.
You could use a List which you sort then.
import java.util.List;
import java.util.Collections;
public class Main {
public static void main (String[] args) {
boolean run = true;
List<String> names = new List<String>();
while (run) {
String name = getString ();
if (name == "q") run = false;
else
names.add (name);
}
Collections.sort (names);
// Results:
System.out.println (names.get (0)); // Print out first entry
System.out.println (names.get (names.size() - 1)); // ... and last one
}
public static String getString () {
// Your method
}
}
In order to sort names you should use a collection that sorts the elements as you put them in.
For this porpose you can use the TreeSet implementation which is a sorted Set. Set also makes sure that no repeating elements are stored (for this it uses the compareTo method of the elements).
Also you can create a Collator object (which implements the comparator interface), which can use a locale object to sort the elements. It's easy to do localization based sorting with this method.
Please see the example below:
public static void main(String[] args) {
// Create the locale object
// This will be used when sorting the elements
Locale myLocale = Locale.ENGLISH;
// Locale myLocale = new Locale("HU", "hu");
// Locale myLocale = Locale.getDefault();
// Create the collator which will be responsible for using the locale object in order to compare the elements in the TreeSet
Collator coll = Collator.getInstance(myLocale);
coll.setStrength(Collator.PRIMARY);
// TreeSet for storing the elements
// Note that the TreeSet is instantiated with the collator object
TreeSet<String> names = new TreeSet<>(coll);
names.add("bob");
names.add("david");
names.add("alex");
names.add("charlie");
// You can call first and last method to get the first and last element sorted
System.out.println(names.first());
System.out.println(names.last());
}
I think this is the easiest, fastest, and most professional way of sotring elements since in this case you let java do the sorting for you, you only need to configure the way it should do it.
I hope this will be useful.
The purpose of the program is to calculate the volumes of different geometrical figures (Like a cylinder or a pyramid). I've started out by adding a list where the user can choose between the different figures.
The problem is that I don't know how to make the program know which formula to use. I need to be able to separate the choices instead of just making an int out of the answer.
private void btnAktiveraActionPerformed(java.awt.event.ActionEvent evt) {
String form = listForm.getSelectedValue().toString();
int fo = Integer.valueOf( form );
String höjd = txfHöjd.getText().toString();
int hö = Integer.valueOf( höjd );
String bredd = txfBredd.getText().toString();
int br = Integer.valueOf( bredd );
String radie = txfRadie.getText();
int ra = Integer.valueOf(radie);
String djup = txfDjup.getText();
int dj = Integer.valueOf(djup);
double ACyl = 3.14*ra*ra*hö;
double APyr = (br*dj*hö)/2;
double AKub = br*dj*hö;
double ARät = br*dj*hö;
txfHöjd.setEnabled(false);
txfBredd.setEnabled(false);
txfDjup.setEnabled(false);
txfRadie.setEnabled(false);
listForm.setEnabled(false);
}
private void btnBeräknaActionPerformed(java.awt.event.ActionEvent evt) {
// I know this code won't work, its just a reminder.
if (answer == Cyinder){
System.out.print("volymen är: "+ACyl+" cm^3");
}
}
I don't understand your question very clearly. I would suggest to make a plan to solve your problems.
make a list of figures that program will calculate
make a list of methods to count volumes of those figures
create individual classes, variables etc...
create methods
create main method with user input
You mentioned you don't know which formula to use. I assume there won't be many formulas in your program. I would create an individual method for each individual figure i.e. piramidFormula(), cilinderFormula()...
There is no point to refer to polimorphism when I think your level of programming is very basic at this stage.
I hope that will help you a little bit.
You need a list to hold the things, you seem to understand this just fine.
You need a way to select things. Selection is typically not exactly the same thing as the list, you need a class to be responsible for the "selection" behaviour.
Each thing has a routine that can calculate the volume. That means it will need input parameters. This is where it starts to get tricky, because if you want all of your things to be in the same list, you need to decide how to manage the different input parameters for the different types in the list.
public List<VolumeCalculations> volumeCalculations ...
public interface VolumeCalculation {
public double getVolume();
}
public class CubleCalcuation implements VolumeCalculation {
private double side = 0;
public void setSide(double value) {
this.side = value;
}
#Override
public double getVolume() {
return side*side*side;
}
}
the other volume calculations are left as an exercise to you.
Then you need to put them all in the list
volumeCalculations.add(new CubeVolumeCalculation());
...
But when you select the calculation, you will need "something" to ask for the right input.
public interface CalculationInputGather {
public void setCalcualtion(VolumeCalcuation value);
public void askForInputs();
}
which the one for the CubleCalcuation might look like
public CubeInputGather implements CalculationInputGatherer {
#Override
public void setCalculation(VolumeCalcualtion value) {
if (value instanceof CubeCalcuation) {
this.volume = value;
}
throw new IllegalArgumentException("value must be a CubeCalculation");
}
public void askForInputs() {
System.out.println("enter the side value:");
// read the value
volume.setSide(value);
}
}
then when you know the selected item in the list, you can use a Map of Calcuations to their input gatherers to lookup the right input gatherer for the selected calcuation.
If you already have the list for the user to choose from, maybe consider a map instead. You can have all your shapes as the keys of the map and then the formulas for volume as the values of the map. The list of shapes can be provided to the user via the keySet and their response can be matched back against the map to find the formula.
EDIT: You have your formulas for each shape inside an action event. You'll need to move those into a separate class
public static class Formulas() {
// list all formulas here
private String cylinder = "3.14*r*r*h";
}
Then when you hit the action you can either create a new instance of the Formulas class and use any convenience methods you might write in there.
I have two strings which are mentioned below -
HelloWorld
GoodBye
How do I randomly select any one of the strings?
Below is an enum which contains the above two strings and I am supposed to use below enums to randomly select any one of the string between HelloWorld and GoodBye
public enum StringEnum {
HelloDavid, HelloWorld, GoodBye;
private static final Map<Integer, StringEnum> BY_CODE_MAP = new LinkedHashMap<Integer, StringEnum>();
static {
for (StringEnum rae : StringEnum.values()) {
BY_CODE_MAP.put(rae.ordinal(), rae);
}
}
public static String forCode(int code) {
return BY_CODE_MAP.get(code).name();
}
}
Any idea how this can be done efficiently by getting the strings from enum?
Usually you would put all the elements you want to choose from in some data structure like an array and then select a random index to fetch.
In your example this could look something like this: (I assume, that you actually want to choose from all enum values and you want back the enum value rather than the String)
int idx = new Random().nextInt(StringEnum.values().length);
StringEnum random = StringEnum.values()[idx];
Also see questions like "Random element for string array" for more information about generally selecting random elements.
For the simpler case of really only choosing between the two mentioned elements, you could just retrieve one random integer and decide based on whether it is positive (including 0) or negative:
StringEnum random = (new Random().nextInt() < 0) ?
StringEnum.HelloWorld : StringEnum.Goodbye;