Creating new objects from array to array - java

I'm trying to generate new unique objects from an array of all possible objects to another array. The idea is that I have 3 classes that implement Region class and they have their own methods. These 3 classes are in my ArrayList<Region> arr. I pick a random class and add it to ArrayList<Region> ALL_REGIONS in a for loop. The problem is that the object that is added from arr is not unique, they are the same. This ca be told by their name. Every Region must have it's unique name and other settings but they don't. So this is the code I have so far:
public void generateRegions(){
ArrayList<Region> arr = Regions.getAllRegions();
Random rnd = new Random();
String ntype;
int regcounter = 5;
int b;
for(int i = 0; i < regcounter; i++){
ALL_REGIONS.add(arr.get(rnd.nextInt(arr.size())));
ntype = "n" + ALL_REGIONS.get(i).getType();
b = rnd.nextInt(Regions.getNtypeSize(ntype));
UI.print("b: " + b);
ALL_REGIONS.get(i).setName(Regions.getArrayName(ntype, b));
}
}
public static ArrayList<Region> getAllRegions(){
ArrayList<Region> arr = new ArrayList<Region>();
arr.add(new Highlands());
arr.add(new Cave());
arr.add(new Oasis());
return arr;
}
getArrayName returns a String name of the Region from an array and getNtypeSize returns an int, size of the array String[] that contatins all names which is not really important just now.
So.. how can I have every Cave, every Oasis unique/as a separate object?
**EDIT: ** Requested getArrayName() and getNtypeSize() methods are below:
public static String getArrayName(String ntype, int t) {
String ans = null;
if(ntype.equals("ncave")){
if(t<=ncaveSize)
ans = ncave[t];
}else if(ntype.equals("noasis")){
if(t<=noasisSize)
ans = noasis[t];
}else if(ntype.equals("nhighlands")){
if(t<=noasisSize)
ans = nhighlands[t];
}
//Can happen when t is bigger then ntype size or
// if ntype string is wrong
if(ans == null){
UI.printerr("getArrayNames: ans is empty/null");
}
UI.printerr(ans);
return ans;
}
public static int getNtypeSize(String ntype){
int ans = 0;
if(ntype.equals("ncave")){
ans = ncaveSize;
}else if(ntype.equals("noasis")){
ans = noasisSize;
}else if(ntype.equals("nhighlands")){
ans = nhighlandsSize;
}else
UI.printerr("getNtypeSize: returned 0 as an error");
return ans;
}

The issue is in this line:
ALL_REGIONS.add(arr.get(rnd.nextInt(arr.size())));
Here, you're not adding a new object to ALL_REGIONS. Rather, each time you're adding a reference to an object in 'arr'.
For example, each time rnd.nextInt(arr.size()) returns 2, you would add a reference to arr[2] to ALL_REGIONS. Thus, effectively, each entry in ALL_REGIONS refers to one of the objects in arr. (In this specific example, one of 3 objects you added in getAllRegions())
Effectively, this means that every Highlands object reference in ALL_REGIONS points to the same object => arr[0]
Similarly, every Cave reference in ALL_REGIONS points to arr[1] and every Oasis reference points to arr[2]
Something along this line should fix the issue:
Region reg = arr.get(rnd.nextInt(arr.size()))
ALL_REGIONS.add(reg.clone()); // this is just meant to be a sort of pseudo-code. Use a clone() method to create a new copy of the object and that copy to ALL_REGIONS.

If I got it right? You want to cast back to the type of the original object. It is plenty easy to do so, you will use some of the Java Polymorphism concepts.
You will use a function called InstanceOf like this
Region ob = arr[0];
if (ob instanceof Highlands)
Highlands newOb = (Highlands) ob;

Related

Changing initial value of a for loop

I am trying to add Books in my code. Let's say someone wants to add 30 books, the iteration goes from 0 to 30 which is fine. What if he wants to add 10 more books later, then it will simply do nothing useful, since I need them to start from 30 to 40. How can I fix this?
int currentBooks = 0;
do {
System.out.print("How many books would you like to add? ");
int nbBooks = sc.nextInt();
// Add nbBooks amount to inventory array
if (inventory.length-currentBooks >= nbBooks) {
for (int w = 0; w < inventory.length; w++) {
inventory[currentBooks] = new Book();
currentBooks = w;
}
valid = true;
break password;
}
else {
System.out.print("You can only add " + inventory.length + " books.\n");
add = true;
}
} while(add);
The disadvantage of a plain array (Book[] in your case) is that its length cannot be changed. You should use a List (despite the fact that you're not allowed to, for some strange reason).
With the List interface
Therefore, you are better off using the List interface (and an implementation of it, for instance, ArrayList), which uses an array internally, but it automatically extends its internal array if needed, so you don't have to worry about it:
// List is an interface, so we need a certain implementation of that interface
// to use. ArrayList is a good candidate:
List<Book> books = new ArrayList<>();
Now we have created an ArrayList with the initial length of 0. The length can be obtained using the size() method, as opposed to an array's length property.
int nbBooks = sc.nextInt();
for (int i = 0; i < nbBooks; i++) {
books.add(new Book());
}
Without the List interface
However, if you cannot or may not use the List interface, you have a few options, depending on what exacly you want.
One of the options is to create a class which holds your array with Books, and a length as a property, because you have to store the length somewhere:
class BookList {
private Book[] books = new Book[100]; // Or some maximum length
private int size;
public void add(Book book) {
this.books[this.size] = book;
this.size++;
// You could optionally 'extend' the array with System.arraycopy
// when the internal array exceeds 100, but I'll leave that to
// you
}
}
Note that this is virtually a kind of homebrew version of the ArrayList class.
In your case you have defined inventory somewhere. You'll need to introduce inventorySize or something, and each time you add a book, you also increment the inventorySize variable.
Book[] inventory;
int inventorySize;
and your method:
...
System.out.print("How many books would you like to add? ");
int nbBooks = sc.nextInt();
for (int i = 0; i < nbBooks; i++) {
this.inventory[this.inventorySize + i] = new Book();
}
this.inventorySize += nbBooks;
You can also check for the last non-null element (or the first null element) and consider that the length of the array, but that would be very bad code, because, for instance, you have to walk over the array to calculate its length, which might be pretty expensive in performance.

Working with new object changes reference too

I have this list of objects that includes an array i (want) to use just as reference. So when i create a new object, fill it with an array in the list and start changing that new object i do not want my initial arrays for the object in my list to change.
I basically do this:
//Fill list with my reference objects;
Object newObject = new Object(); //So i do not change the previous newObject in the loop.
newObject = (find)ObjectFromList;
newObject.array = RotateArray(newObject.array);
If i fill another newObject with the same object from the list it already is rotated. I hope i have been clear enough. Below a shortened version of my code, still a bit messy too:
LoadRooms(); //Loads all the objects and arrays from a file into the list.
for(int x=0;x<width;x++)
{
for(int y=0;y<height;y++)
{
Room newRoom = new Room();
//Fill newroom with correct room type, rotate and build tilemap.
//Dead ends
if(!mazeMap[x][y].N && !mazeMap[x][y].E && mazeMap[x][y].S && !mazeMap[x][y].W)
{
newRoom = FindRoom(Room.RoomType.DeadEnd);
newRoom.room = TurnRoomCW(newRoom.room);
newRoom.room = TurnRoomCW(newRoom.room);
newRoom.room = TurnRoomCW(newRoom.room);
}
else if(!mazeMap[x][y].N && mazeMap[x][y].E && !mazeMap[x][y].S && !mazeMap[x][y].W)
{
newRoom = FindRoom(Room.RoomType.DeadEnd);
}
//Etc, etc then i build a map from the newRoom.room array
}
}
This is what TurnRoom() looks like:
private String[][] TurnRoomCW(String[][] room)
{
String[][] rotatedRoom = new String[room[0].length][room.length];
for (int y = 0; y < room[0].length;y++)
{
for (int x = 0;x < room.length;x++)
{
rotatedRoom[y][x] = room[7 - x][y];
}
}
return rotatedRoom;
}
and here is FindRoom
private Room FindRoom(Room.RoomType roomType)
{
Collections.shuffle(rooms, rand);
for (Room r : rooms)
{
if (r.roomType.equals(roomType))
return r;
}
return null;
}
When i want to turn something like a corner type room, say NE into the correct position all other rooms turn with it. So when i want to turn, say SW into position the NE will be position wrong again.
Your FindRoom method is returning a reference to the actual room.
'TurnRoomCW' returns a new object, but you then assign that new object back into the original room
So your problem is right here:
newRoom = FindRoom(Room.RoomType.DeadEnd); // 1) find a DeadEnd room
newRoom.room = TurnRoomCW(newRoom.room); // 2) create rotated room, assign it to the room from step 1)
If you want to work with a new Room object, you will need to create a new one somehow. For example, you might define a constructor for Room that returns a new object initialized from an existing one. For example,
/** copy constructor */
public Room(Room oldRoom) {
this(); // regular constructor
this.room = oldRoom.room.clone(); // new Room gets its own array!
this.roomType = oldRoom.roomType;
// … etc for any other member variables
}
Basically, Java objects are references (pointers if you prefer), so unless you make an explicit copy of an Array (or any other object), it will point to the same object.
If you want to avoid that, you have to do a clone first:
List myList = referenceList.clone();
This is generally a good habit anyway to avoid having your "internal" object being modified by the external world.

Array in Method Header: error ']' expected (Java)

I'm quite new to arrays and methods, and I've been seeing this error recurring through several programs: error '[' expected.
In each occasion, it seems to correct itself as I adjust something else, but in this particular case, I am completely stumped.
By the way, I am using several methods and arrays to create a quiz (before you ask, yes, this is an assignment and I agree, a list is a better way to handle this data - but that is not an option).
It is possible that I am not passing the arrays correctly between methods, as I'm a little muddy on that process. From my understanding, in order to send/receive (i.e. import/export) an array or other variable between methods, I must declare that variable/array in the method header parameters.
import java.util.Scanner;
public class H7pseudo
{
public static void main(String[] args)
{
//call getAnswerkey method
getAnswerkey(answerkey[i]);
//call getAnswers method
getAnswers(answers[i]);
//call passed method? necessary or no?
boolean passed = passed(answerkey[i], answers[i], qMissed[i], points);
//Print results of grading
if (passed)
{
System.out.println("Congratulations! You passed.");
}
else
{
System.out.println("Try again, sucka. You FAILED.");
}
//call totalPoints
totalIncorrect(points);
//call questionsMissed
questionsMissed(qMissed[i]);
}
//get answer key (create answerkey array & export)
public static void getAnswerkey(answerkey[i])
{
//create answerkey array here
char[] answerkey;
//determine number of questions (indices)
answerkey = new char[20];
//input values (correct answers) for each index
//for our purposes today, the answer is always 'c'.
for (int i = 0; i <=20; i++)
{
answerkey[i] = 'c';
}
}
//get student answers (create answers array & export)
public static void getAnswers(answers[i])
{
//initialize scanner for user input
Scanner scan = new Scanner(System.in);
//create answer array here
char[] answers;
//determine number of questions (indices)
answers = new char[20];
//prompt for user input as values of each index
for (int i = 0; i <= 20; i++) {
answers[i] = scan.nextChar();
}
}
//grade student answers (import & compare index values of arrays:answers&answerkey
//create & export qMissed array
public static boolean passed(answerkey[i], answers[i], qMissed[i], points)
{
int points = 0;
//create new array: qMissed
boolean[] qMissed;
//determine number of questions to be graded
qMissed = new boolean[20];
//initialize values for array
for (int i = 0; i <= 20; i++) {
qMissed[i] = false;
}
//cycle through indices of answerkey[i] & answers[i];
for (int i = 0; i =< 20; i++)
{
if (answers[i] == answerkey[i])
{
correct = true;
points = points+1;
qMissed[i] = true;
}
else {
qMissed[i] = false;
}
}
//evaluate whether or not the student passed (15+ correct answers)
if (points >= 15)
{
passed = true;
}
else
{
passed = false;
}
return passed;
}
public static void totalIncorrect(points)
{
int missed = 20 - points;
System.out.println("You missed " + missed + " questions.");
}
public static void questionsMissed(qMissed[i])
{
// for each index of the array qMissed...
for (int i = 0; i < qMissed.length; i++)
{
//...print correct and false answers.
system.out.println(i + ": " + qMissed[i] + "\n");
}
}
}
You can't define array size in the method signature, in Java.
public static void getAnswerkey(answerkey[i])
You can't put anything inside the [] in a method declaration. Also, you have to mention the type:
public static void getAnswerKey(char[] answerkey)
This is not the only reason your code won't work as intended, but I'll leave the rest as part of the exercise.
Look at your method definitions:
public static void questionsMissed(qMissed[i])
This is wrong. You should define the type of the variable and it should not contain [i] like an element of an array. It should be something like this:
public static void questionsMissed(int qMissed)
Or if you want to pass the array, write it like this:
public static void questionsMissed(int[] qMissed)
Apart of this, there are other several errors in your code:
getAnswerkey(answerkey[i]); //answerkey is not defined
getAnswers(answers[i]); //answers is not defined
It would be better if you start reading a Java tutorial first.
I want to vote up Luiggi's answer, but I don't have enough reputation to do that :)
Congrats, cordivia, on getting started with Java!
Here is how an array is declared:
type[] arrayName = new type[numberOfElements]
For example, you did this right in your method definition for getAnswerkey():
char[] answerkey;
answerkey = new char[20];
The part in the method definition inside the parentheses defines the kind of data the method is willing to accept from the outside. So if you don't need to put something into the method to get something out of it, you don't need to put anything in the parentheses. Define the method like this:
getAnswerkey() {
...But that's not the whole story. If you want to get something out of the method, it needs to have a return type as well. A return type is what you're gonna get out of the method when the method's done doing it's magic. For example, if you want to get an int array out of a method you would do something like this:
public static int getTheInteger() {
Since you want an array of chars from the method, you'll want to do something like this:
public static char[] getAnswerkey() {
So that's how you get a method to give you something back. If don't want anything back, you put void:
public static void noMarshmallows() {
Now, when you use the method, you're gonna need to do something with what it gives you, or it did all that work for nothing. So you need to store the return value in a variable when you call the array (calling methods is what you've been doing in main). You know how to store something in a variable. You use the '=' operator:
int myVeryFavoriteNumber;
myVeryFavoriteNumber = 5;
So, you do the same thing when you're getting something out of an array. You assign the return value to a variable. If you want to do this with an array, do this:
int[] myFavs;
myFavs = getMyFavoriteNumbers();
Same with chars:
char[] answerKey;
answerKey = getAnswerKey();
Voila! Your answer key is now right out in the open for the rest of main to see :)
Now, if you want to put something into a method and have it do something with what you put in, you define a parameter. You know how this works. It's just like declaring a variable, and that's exactly what it is. Parameters go in the parentheses and only the method using the parameter sees that variable name (it's local). Something like this:
public static void plusOneToAll (int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i] + 1;
}
}
Notice int[] numbers in the parentheses. The type being passed in is int[] or integer array. numbers is just the parameter name. It functions just like a variable, but it is declared locally (inside the parentheses) and use locally (inside the method). So, if you wanted to compare the answers from two arrays and return the number of matches (like a total score for instance), you would do something like this:
public static int getTotalScore (char[] correctAnswers, char[] userAnswers) {
int totalScore = 0;
for (int i = 0; i < correctAnswers.length; i++) {
if (userAnswers[i] == correctAnswers[i]) {
totalScore = totalScore + 1;
}
}
return totalScore;
}
Notice the return type: int (written before the method name). Inside the array I'm using the variable totalScore to keep track of the number of times the answers match. The method takes two char arrays from the outside and uses them on the inside. Finally, I return an int: totalScore. That kicks the value of totalScore back out to whatever called it (main).
If I might add one last thing: Do yourself a favor and go pick up a copy of Head First Java. It's hard to find a good tutorial online and Java textbooks are just plain boring. The Head First series are kind of like coloring books for adults.
Best of luck!

need to store value after passing to method for latter check

I am passing few values to mail method for sending the details like below
private static String getTeam(String Team, List<String> prioritys1, String number,String description
) {
StringBuilder builder1 = new StringBuilder();
for (String v : prioritys1) {
if ( v == "1") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
else
if ( v == "3") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
}
return builder1.toString();
}
I tried to store in arrays but it didnt worked.
I after pass above parameters, i need to store the value of the number. i need to store the number so that next time while passing the parameters i need to check first whether the number is already passed or not if not then only i need to pass to mail.
can any one help on this
With this code very complicated understand what you are doing. But if you need check value that already been processed store it outside of the method. Create global class variable:
public class className {
private final List<String> ARRAY = new ArrayList<>(); // global variable
public void yourMethod(String value) {
if (!ARRAY.contains(value)) {
mail(value);
ARRAY.add(value);
}
}
}
I dont know your case and I can not get better example.
You need to store the value in a "class level" variable. Whether the variable type needs to be static or instance will depend on your implementation of the method.
If you can post a sample code, we can help further.
You need to compare with 2 equals and not 1
Instead of
if( Team = A )
you need this way
if( Team == A )
Using Team = A, your saying that every time your code reaches that line it will equal Team to A.

How do I add an element to the end of my array?

I don't know if this is right, so I need your comments guys. I have an array of employee names. It will be displayed on the console, then will prompt if the user wants to insert another name. The name should be added on the end of the array(index 4) and will display again the array but with the new name already added. How do I do that? Btw, here's my code. And I'm stuck. I don't even know if writing the null there is valid.
public static void list() {
String[] employees = new String[5];
employees[0] = "egay";
employees[1] = "ciara";
employees[2] = "alura";
employees[3] = "flora";
employees[4] = null;
for(int i = 0; i < employees.length; i++) {
System.out.println(employees[i]);
}
}
public static void toDo() {
Scanner input = new Scanner(System.in);
System.out.println("What do you want to do?");
System.out.println("1 Insert");
int choice = input.nextInt();
if(choice == 1) {
System.out.print("Enter name: ");
String name = input.nextLine();
You can't, basically.
Arrays have a fixed size when they've been constructed. You could create a new array with the required size, copy all the existing elements into it, then the new element... or you could use a List<String> implementation instead, such as ArrayList<String>. I'd strongly advise the latter approach.
I suggest you read the collections tutorial to learn more about the various collections available in Java.
Also note that you've currently just got a local variable in the list method. You'll probably want a field instead. Ideally an instance field (e.g. in a class called Company or something similar) - but if you're just experimenting, you could use a static field at the moment. Static fields represent global state and are generally a bad idea for mutable values, but it looks like at the moment all your methods are static too...
Arrays are fixed in size. Once you declare you can not modify it's size.
Use Collection java.util.List or java.util.Set. Example ArrayList which is dynamic grow-able and backed by array.
If you really have to use arrays then you will have to increase the size of the array by using an intermediate copy.
String[] array = new String[employees.length + 1];
System.arraycopy(employees, 0, array, 0, employees.length);
array[employees.length] = newName;
employees = array;
However, the best way would be to use a List implementation.
It depends on whether the user can enter more than 4 employee names. If they can then using ArrayList is the better choice. Also the employees variable needs to be a static property of your class since being used in a static method.
private static String[] employees = new String[5];
static {
employees[0] = "egay";
employees[1] = "ciara";
employees[2] = "alura";
employees[3] = "flora";
employees[4] = null;
}
public static void list() {
for(int i = 0; i < employees.length; i++) {
System.out.println(employees[i]);
}
}
public static void addEmployeeName(String name, int index) {
employees[index] = name;
}
Here you are using static array which is fixed at the time of creation.I think you should use
java.util.Arraylist which will provide you facility of dynamic array.

Categories