a set indexed objects in ArrayList - is it possible? - java

Is it possible to create a set indexed objects in ArrayList?
I want to create an array of objects - Portal class - and have them indexed in array which size will be defined by user.
import java.util.ArrayList;
import java.util.Scanner;
public class GameFunctions
{
Scanner sc = new Scanner(System.in);
private int portalsQty;
private String[] portalNamesDB = {"name1", "name2", "name3", "name4", "name5"};
ArrayList<Portal> portals = new ArrayList<>();
void setPortalsQty(int portalsQty)
{
this.portalsQty = portalsQty;
}
int getPortalsQty(int portalsQty)
{
return portalsQty;
}
private void createPortals()
{
System.out.println("type the
amount of portals");
portalsQty = sc.nextInt();
System.out.println("number of portals: " + portals.size());
for (int i = 0; i < portalsQty; i++)
{
portals.add(i,p[i]); // CANNOT HAVE VALUES INDEXED LIKE p[i] IN ARRAYLIST
}
}
private void namePortals()
{
int randomNo = (int)(Math.random()*portalsQty);
for (int i = 0; i < portalsQty; i++)
{
System.out.println("Random: " + randomNo);
portals[i].setPortalName(portalNamesDB[randomNo]);
}
}
public void launchGame()
{
createPortals();
namePortals();
}
}
Defining the size of array by user makes using tables not feasible, as we encounter NullPointerException.
Is there any other solution to make dynamic size of the table and have the elements indexed?

import java.util.HashMap;
HashMap<Integer, portal>portals = new HashMap<>();
System.out.println("number of portals: " + portals.size());
for (int i = 0; i < portalsQty; i++)
{
int randomNo = (int)(Math.random()*portalsQty);
portals.put(portalNamesDB[randomNo], i);
}
Mureinik and chrylis are right, a map, or HashMap would probably work best here.
I added an example of how you could implement it. This way you are giving each portal a name and quantity value all in one for loop. The portal name is the key, and the quantity number is the value in my example.
I hope that helps!

You could emulate this behavior with a map that maps from the index to the object:
Map<Integer, Portal> indexes = new HashMap<>();

Related

Get value from HashMap by key

I need to compare the roman letters and get the correct integer out of it.
If I'm correct, there should be a way to compare the hashmap key with the arraylist element and if they match, get the associated value from the key.
The return 2020 is there just for test purposes, since I wrote a JUnit test in a different class. It can be ignored for now.
I hope someone could give me a hint, since I wouldn't like to use the solutions from the web, because I need to get better with algorithms.
package com.company;
import java.util.*;
public class Main {
static HashMap<String, Integer> romanNumbers = new HashMap<String, Integer>();
static {
romanNumbers.put("I", 1);
romanNumbers.put("V", 5);
romanNumbers.put("X", 10);
romanNumbers.put("L", 50);
romanNumbers.put("C", 100);
romanNumbers.put("D", 500);
romanNumbers.put("M", 1000);
}
public static void main(String[] args) {
romanToArabic("MMXX");
}
static int romanToArabic(String roman) {
ArrayList romanLetters = new ArrayList();
roman = roman.toUpperCase();
for (int i = 0; i < roman.length(); i++) {
char c = roman.charAt(i);
romanLetters.add(c);
}
// [M, M, X, X]
System.out.println(romanLetters);
// iterates over the romanLetters
for (int i = 0; i < romanLetters.size(); i++) {
System.out.println(romanLetters.get(i));
}
// retrive keys and values
for (Map.Entry romanNumbersKey : romanNumbers.entrySet()) {
String key = (String) romanNumbersKey.getKey();
Object value = romanNumbersKey.getValue();
System.out.println(key + " " + value);
}
return 2020;
}
}
You could just Map.get each array element.
package com.company;
import java.util.ArrayList;
import java.util.HashMap;
public class Main {
static HashMap<String, Integer> romanNumbers = new HashMap<String, Integer>();
static {
romanNumbers.put("I", 1);
romanNumbers.put("V", 5);
romanNumbers.put("X", 10);
romanNumbers.put("L", 50);
romanNumbers.put("C", 100);
romanNumbers.put("D", 500);
romanNumbers.put("M", 1000);
}
public static void main(String[] args) {
System.out.println(romanToArabic("MMXX"));
}
static int romanToArabic(String roman) {
ArrayList romanLetters = new ArrayList();
roman = roman.toUpperCase();
for (int i = 0; i < roman.length(); i++) {
char c = roman.charAt(i);
romanLetters.add(c);
}
// [M, M, X, X]
System.out.println(romanLetters);
// iterates over the romanLetters
int sum = 0;
for (int i = 0; i < romanLetters.size(); i++) {
String key = String.valueOf(romanLetters.get(i));
if (romanNumbers.containsKey(key)) {
sum += romanNumbers.get(key);
}
}
return sum;
}
}
As stated in the comments, this just answers your question of how to get values from an hashmap where keys are the array elements. It is not a solution to calculate the numeric value out of a roman number. For that, you will have to look at the next letter, and join if it is larger, before consulting the map for the final value to sum.
I'd like to suggest a completly different approach using an enum.
public enum RomanNumber {
I(1), V(5), X(10), L(50), C(100), D(500), M(1000);
private final int arabic;
RomanNumber(int arabic) {
this.arabic = arabic;
}
public int getArabicNumber() {
return arabic;
}
// This is obviously broken. IV wouldn't work for example.
public static int toArabic(String romanLetters) {
romanLetters = romanLetters.toUpperCase();
int arabicResult = 0;
for (int i = 0; i < romanLetters.length(); i++) {
char romanNumber = romanLetters.charAt(i);
// valueOf(String) returns the enum based on its name. So a String of "I" returns the RomanNumber I enum.
int arabicNumber = valueOf(String.valueOf(romanNumber)).getArabicNumber();
arabicResult = arabicResult + arabicNumber;
}
return arabicResult;
}
}
Can be used like this:
String romanNumber = "MMXX";
System.out.println(RomanNumber.toArabic(romanNumber));
Btw. every enum has an ordinal() method which returns the declaration position inside the enum. (I.ordinal() == 1 or V.ordinal() == 2) I think this could help you with the IV problem aswell. :)

How to change an array into an ArrayList? (generics)

I have a task to change a type of a variable into ArrayList and I need to initialize it as an ArrayList. I don't know how to do it :(
I tried this in a such way:
private ArrayList<T> warehouseContent = new ArrayList<T>();
public void registerProducts(Product... products) {
WarehouseItem[] updatedWarehouseContent = new WarehouseItem[warehouseContent.size()
+ products.length];
int i = 0;
for (; i < warehouseContent.size(); i++) {
updatedWarehouseContent[i] = warehouseContent[i];
}
for (; i < updatedWarehouseContent.length; i++) {
updatedWarehouseContent[i] = new WarehouseItem(products[i - warehouseContent.size()]);
}
warehouseContent=updatedWarehouseContent;
}
But I think it isn't correct. The source code which I need to change is below:
private WarehouseItem[] warehouseContent = new WarehouseItem[0];
public void registerProducts(Product... products) {
WarehouseItem[] updatedWarehouseContent = new WarehouseItem[warehouseContent.length
+ products.length];
int i = 0;
for (; i < warehouseContent.length; i++) {
updatedWarehouseContent[i] = warehouseContent[i];
}
for (; i < updatedWarehouseContent.length; i++) {
updatedWarehouseContent[i] = new WarehouseItem(products[i - warehouseContent.length]);
}
warehouseContent=updatedWarehouseContent;
}
Could someone give me any tips or explain me what I need to use here a generic type ArrayList?
Start by declaring the warehouseContent type as a list of WarehouseItem:
private List<WarehouseItem> warehouseContent = new ArrayList<>();
Now you can rely on ArrayList's built-in ability to grow in your registerProducts method:
public void registerProducts(Product... products) {
for (Product product : products) {
warehouseContent.add(new WarehouseItem(product));
}
}
This one loop does what the two loops and an allocation of your original implementation did. Note that copying the content of an old array into the new one is still there, but it is encapsulated in the add method of ArrayList.

Task dealing with sorting 2d array

I have been assigned a task that requires me to utilise a 2D Array. I have to read in a file and export it to a 2D array. I can only have a single method but I am unable to sort the array correctly. I am supposed to sort the data in 3 ways (alphabetically by name and with scores highest to lowest; highest to lowest scores for each student and highest to lowest by the average of 3 scores.) So far I have
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
I have no idea as to how to solve the rest of the task... I would appreciate if someone could tell me of the most efficient way and perhaps an example...
One plausible way is to create a Student class which implements Comparable interface, with the following members:
String name;
int scoreOne;
int scoreTwo;
int scoreThree;
compareTo(Student s) { //implement the comparison following 3 criteria you mentioned }
And, read the files row by row, for each row we create a Student object, and put all rows in a TreeSet. In this way, the TreeSet together with the compareTo method will help us sort the Students automatically.
Finally, iterate the sorted TreeSet to fill up the 2D array.
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
/*Code To be Inserted Here*/
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
If there are 6 columns such that First is name and the other 3 are scores then what does other 2 columns contain?? I ignore your array declaration :
String[][] DataInTableArr = new String[30][6];
and assume it to be 30x4 array
String[][] DataInTableArr = new String[30][4];
Logic for sorting Alphabetically
if(DataInTableArr[i][0].compareTo(DataInTableArr[i+1][0])){
/* Sorting Name of adjacent rows*/
String temp = DataInTableArr[i][0];
DataInTableArr[i][0] = DataInTableArr[i+1][0];
DataInTableArr[i+1][0] = temp;
/*Sorting the three marks similarly*/
temp = DataInTableArr[i][1];
DataInTableArr[i][1] = DataInTableArr[i+1][1];
DataInTableArr[i+1][1] = temp;
temp = DataInTableArr[i][2];
DataInTableArr[i][2] = DataInTableArr[i+1][2];
DataInTableArr[i+1][2] = temp;
temp = DataInTableArr[i][3];
DataInTableArr[i][3] = DataInTableArr[i+1][3];
DataInTableArr[i+1][3] = temp;
}
Put the above code in bubble sorting algorithm i.e. 2 loops.
Logic for sorting according to highest marks
In this case you have to find the highest marks in all three subjects of each DataInTableArr[i] and then compare the highest marks with that of next row.
Logic for sorting according to Average marks
Calculate the average of each i'th row as
(Integer.parseInt(DataInTableArr[i][1]) + Integer.parseInt(DataInTableArr[i][2]) + Integer.parseInt(DataInTableArr[i][3]))/3
and compare it with [i+1] th rows average.(same formula just replace [i] with [i+1])

Java - Printing Array List of String Arrays

I am pretty new to Java and had a question. This is homework, so I would not like any outright answers. Thanks!
I'm working on a genetic algorithm for playing poker. I wanted to create an arrayList of string arrays. The string arrays would hold moves for each possible hand during a round. What I want to do right now to make sure it is working is run my method and print out the results. Here are my practice classes (this is only a small part of the assignment):::
import java.util.ArrayList;
import java.util.Arrays;
public class Play
{
GeneticAlg start;
ArrayList<Object> pop;
public static void main(String[] args)
{
GeneticAlg start = new GeneticAlg();
ArrayList<String[]> pop = start.initializePopulation();
for(String[] arr: pop)
{
System.out.println(Arrays.toString(arr));
}
}
}
import java.util.ArrayList;
import java.util.Random;
public class GeneticAlg
{
ArrayList<String[]> population;
int[] populationScores;
String[] chromosome;
int generation;
int index;
public GeneticAlg()
{
}
public ArrayList<String[]> initializePopulation()
{
ArrayList<String[]> population = new ArrayList<String[]>();
for (int i = 0; i < 20; i++)
{
Random generator = new Random();
String[] choices = {"bet","raise","call","check"};
chromosome = new String[33];
for (int j = 0; j < 33; j++)
{
if (j < 6) //first and second round possible hands)
{
index = generator.nextInt((choices.length)-1);
chromosome[j] += choices[index];
}
else //third, fourth, and fifth round possible hands)
{
index = generator.nextInt(choices.length);
chromosome[j] += choices[index];
}
}
population.add(chromosome);
}
return population;
}
}
Right now, it's printing out the array, but each entry looks like this:
[nullcall, nullraise, nullbet, nullraise, nullcall, nullraise,....
I want it to just return the move without null on the front. Any advice is appreciated. Thanks!
ETA: I fixed the two lines with the concatenation error, but it is still printing "null" in front of each command. Any advice?
Code after repairing the error:
import java.util.ArrayList;
import java.util.Arrays;
public class Play
{
GeneticAlg start;
ArrayList<Object> pop;
public static void main(String[] args)
{
GeneticAlg start = new GeneticAlg();
ArrayList<String[]> pop = start.initializePopulation();
for(String[] arr: pop)
{
System.out.println(Arrays.toString(arr));
}
}
}
import java.util.ArrayList;
import java.util.Random;
public class GeneticAlg
{
ArrayList<Object> population;
String[] choices;
int[] populationScores;
String[] chromosome;
int generation;
int index;
public GeneticAlg()
{
}
public ArrayList<Object> initializePopulation()
{
population = new ArrayList<Object>();
for (int i = 0; i < 20; i++)
{
Random generator = new Random();
for (int j = 0; j < 24; j++)
{
if (j < 6) //first and second round possible hands)
{
choices[0]= "bet";
choices[1]= "raise";
choices[3]= "call";
index = generator.nextInt(choices.length);
chromosome[j] = choices[index];
}
else //third, fourth, and fifth round possible hands)
{
choices[4] = "check";
index = generator.nextInt(choices.length);
chromosome[j] = choices[index];
}
}
population.add(chromosome);
}
return population;
}
}
Arrays of objects (like Stirngs) are filled at start with null values, so doing
chromosome[j] += choices[index];
is the same as
chromosome[j] = chromosome[j] + choices[index];
which is the same as
chromosome[j] = null + choices[index];
So you are concatenating null with choices[index]; which gives you nullbet for instance.
To solve it just use = instead of +=.
Since you don't want an outright answer, look at the code that populates your String[]'s. Your printing's doing the right thing, but the Strings in the array actually are "nullbet," "nullraise," etc.
The error comes from this line here:
chromosome[j] += choices[index];
The += operator, when used with a Strings, will concatenate the right-hand string to the end of the left-hand string. In this case, it tacks on choices[index] to the existing contents of chromosome[j], which will null by default if chromosome is declared as an array of Objects.
You probably meant
chromosome[j] = choices[index];
And accidentally inserted the + because you use population.add() with your list below.
Your "fixed" code looks like it doesn't compile - you're probably still running the previous version. You don't initialize choices ("choices = new String[4]") and you're confusing its indices (0, 1, 3 and 4). Also, if you're trying to add a fourth element to the array later, don't, you can't do that with arrays. And you're assigning an ArrayList to an ArrayList without a cast. You only needed to swap += with = in your original code, it seemed fine otherwise.

Begining java on arrays. trying to group duplicate amounts

I am trying to go through a list of names with amounts.
One array has the name of the person , the other has the amount the person gave i.e. john, 55 sally 40 john 33 sarah 55.
My objective is to total the like names and print out the name of the person and the total amount that was given.
John gave twice so he should total 88. But I am getting the total right but my program is printing the name twice. So john 88 is printing twice... I know its likely because I put it in the first for loop its iterating the entire length of the array.
But I am unsure how to solve this?
import java.util.*;
public class chapterfive {
public static void main (String[]args) {
Scanner in = new Scanner (System.in);
String[]names = new String[4];
int[] scores = new int[4];
for (int i = 0; i<names.length; i++) {
names[i] = in.next();
scores[i] = in.nextInt();
}
int amount = 0;
String firstname = "";
for (int i = 0; i < names.length; i++) {
for (int j=0; j < names.length; j++) {
if (names[j].equals(names[i]))
amount += scores[j];
}
System.out.println(names[i] + " " + amount);
amount = 0;
}
}
}
You can see that they have a relationship like Name -> Score , so if you think more abstract this is a dictionary with Key (Name) and Value (Score) , so you can use another data-structure like a Map or you can use an array and make a class Person , have the arrayOrderer and when you add a new person check if that person exist in the array..
Example :
Map <String , Integer> people = new HashMap<>();
for (int i=0; i<lengthYouWant; i++)
{
String name=in.next();
int score=in.nextInt();
if(people.contains(name)){
score= people.get(name)+score;
}
people.put(name,score);
}
Should be using a Map to simplify things, rather than keeping track of two arrays. But heres a fix that may work (haven't tested it)
String firstname = "";
for (int i = 0; i < names.length; i++) {
int amount = 0;
boolean skip = false;
for (int j=0; j < names.length; j++) {
//need to skip because we have already processed it
if(names[j].equals(names[i]) && i > j) {
skip = true;
break;
}
else if (names[j].equals(names[i])) {
amount += scores[j];
}
}
if(!skip) {
System.out.println(names[i] + " " + amount);
}
}
If you make an array or list of the Person class you can implement Comparable and add a method to help in sorting.
Java is an object-oriented language, which means, among other things, that you can make your own data structures. Using parallel arrays is error prone, and it separates data you want to keep together. So, what do you need to organize this?
First is a way of storing a name and an amount. Call it Donation.
class Donation {
private final String name;
private final int amount;
public Donation(String name, String amount) {
this.name = name;
this.amount = amount;
// EXERCISE: Add error checking.
}
public String getName() { return name; }
public int getAmount() { return amount; }
public String toString() {
return "Name: " + name +", amount: " + amount;
}
}
Notice that this class's variables are final; they can't be changed once set. They are set in the constructor, and there are get methods and a toString method that replaces what you have in your System.out.println statement.
Next, you need a way of storing the data. Don't use arrays. Lists are more flexible.
private static List<Donation> donations = new ArrayList<Donation>();
// and in main:
while (true) {
String name = null;
int amount = 0;
if (in.hasNext()) {
name = in.next();
} else {
break;
}
if (in.hasNextInt()) {
amount = in.nextInt();
} else {
break;
}
donations.add(new Donation(name, amount));
} See -- no 4s.
Next, you need to consolidate the repeated donations. I mean, some people give to their church every Sunday. We'll use the appropriate structure, a Map.
// Also in main:
Map<String, Integer> totals = new HashMap<>();
for(Donation d: donations) {
String name = d.getName();
int amount = d.getAmount();
if (!totals.containsKey(name)) {
totals.put(name, 0);
}
int currentDonation = totals.get(name);
totals.put(name, currentDonation + amount);
}
And then finally, you iterate through the map and print each entry.
for ( Map.Entry<String, Integer> entry: totals.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
And now, another exercise and strategy: stop doing everything in main. Give your ChapterFive class instance variables and methods. Then, write tests for these. Try to find improvements to what I suggested. Then, see if there are libraries that can help you.

Categories

Resources