Why isn't my object being added to my array? - java

I have a ManagementCompany data manager class that stores information about various properties in a Property (a class I defined) type array called properties[]. One of the methods of the class is meant to add properties to that array, and is called addProperty(Property p). It should take the given property and add it to the array in the first available space, if there is any (as seen here:)
Property[] properties = new Property[5];
public int addProperty(Property p) {
if (isArrayFull()) //Method returns true if there is no space, false otherwise
return -1;
else if (p == null) //Make sure p is valid
return -2;
for (int i = 0 ; i < properties.length; i++) { //Loop through all elements in the array
if (properties[i] == null) { //If the space is empty
properties[i] = new Property(p); //Assign a new property to it
return i; //Return the index of the new property
}
}
return -10; //Should never happen, but need it to compile
}
However, when I create and add properties to the array, only the first property is added. After the first property is added, the program doesn't continue adding to the first available space, instead, it seems to just ignore them. It doesn't replace the first one, and doesn't add it to the array (which is initialized to a length of 5). Any suggestions as to why?
Tests I'm running on it:
ManagementCompany mgmCmp = new ManagementCompany();
Property p1 = new Property("Property 1");
mgmCmp.addProperty(p1);
Property p2 = new Property("Property 2");
mgmCmp.addProperty(p2);
System.out.println(mgmCmp.toString());
The result is:
Property 1 null null null null

only the first property is added... Any suggestions as to why?
Because of return i;. You exit the method once you've added one property.
Hope that helps

Found a seemingly unrelated method in another class that was causing the object not to be stored in the array. Thanks for the advice.

Related

How do I detect if a value has been added to array slot? (java)

I am a beginner programmer and i've gotten stuck.
I've set up an array here which has worked how I want it to.
Although now I need a way to check the very last slot (data[5]) to see if any value has been placed within it since there is no guarantee in my code that each array slot will be assigned a value.
Below is my working array setup:
public final int[] data;
//Constructor
public MyArrayList() {
this.data = new int[6];
}
And here is what I've tried:
if(data[5] == null){
data[5] = value;
truth = true;
} else {
truth = false;
}
Note that this code is trying to detect if anything is in there, and place another value in if it can see there hasn't been any code written there.
Any help appreciated :)
int is a primitive type in Java, so it will never be null. If you want to keep track of how much of the array you've "used", you can add a second field to the class to keep up with it.
public class MyArrayList {
private final int[] data;
private int index;
public MyArrayList() {
data = new int[6];
index = 0;
}
...
}
Then whenever you "push" something new to the list, you put it at the index position and increment index. If index is ever equal to the length of the list, then you've exhausted the space you allocated.
Use the Integer class instead of the primitive type. It allows to assign a value or a null value. With this you can apply the logic that you described.
data = new Integer[6];
if (data[5] == null)
data[5] = value;

Why does .contains method on ArrayList of custom instances work?

I've been developing a small application for work, and I've come across something I can't figure out.
In the following code, I have an ArrayList of a Custom Class called 'Product' that contains data of type 'String'. I use the .contains method on this ArrayList to ensure it doesn't contain a certain String.
My IDE gives me the warning of 'Suspicious call to java.util.Collections.contains: Given object cannot contain instances of String (expected Product)'.
I completely understand the above message, because I'm comparing two different Types, so how can it ever evaluate correctly? I'm thinking it must be because the 'Product' class contains the data I want to compare, it is defaulting to using the toString method on the Product class (I override this in the Class) and comparing it with the String I want to compare it against.
It seems like JVM black magic to me.
private void createOrderListing(List<String[]> orderList)
{
//For each line of the order list file
for(String[] s : orderList)
{
if(s.length >= 28) //OrderLine should be of this length
{
if (!s[0].equalsIgnoreCase("ProductCode") && !s[0].isEmpty()) //Makes sure we're not including headers
{
//How does this bit work?
if(!productListing.contains(s[0]))
{
OrderLine order = new OrderLine();
//References product code of Product against Order Line, if match, then pack sizes and other basic fields ammended as appropriate
boolean productFound = false;
for (Product p : productListing)
{
if (s[0].contentEquals(p.getProductCode()))
{
order.initialAmendOrderLine(p.getProductCode(), p.getProductName(), p.getPackSize(), p.getProductType());
productFound = true;
}
}
if(productFound)
{
order.setOrderValues(s);
orderListing.add(order);
}
}
//System.out.println("\nOrder Product is: " + order.getProductName()+ "\nOrder Pack Size is: " + order.getInternalPackSize());
}
}
}
}
UPDATE
The reason this works as pointed out in the comments is that the block is always true (the .contains method is always false, the ! inverses this, hence true). Sorry for the confusion and pointing out my carelessness.
Here is an implementation of contains method in ArrayList that I have in OpenJDK:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Basically, there is nothing complex in it. It iterates through the all elements of your ArrayList and checks whether your given object is equal to the current one. If the condition is true then element exists in the list.
So let's imagine that you are passing String "SomeValue" to this method. Elements of ArrayList are iterated and following action is executed: "SomeValue".equals(elementData[i]) where elementData[i] is a product.
Since equals method of String class cannot compare String with a Product it returns false and as a result, you get false from contains method.
To fix this situation you can iterate over ArrayList manually and compare some Product's field with your string. E.g. you can implement following contains method:
public boolean contains(List<Product> products, String yourStringValue) {
for (Product p : products) {
if(p.getProductCode().equals(yourStringValue)){
return true;
}
}
return false;
}
productListing is a list of Product objects. Yet you are asking the list if it contains a specific String object -- which shouldn't ever happen.
What you should do is check if your Product#getProductCode is equal to your specific String. This can be acheived by using streams:
if(!productListing.contains(s[0])) // replace this
// with this
if (!productListing.stream().filter(o -> o.getProductCode().equals(s[0])).findFirst().isPresent())
What does this code do? It checks all your Product elements to find one whose myStringData attribute is equal to the String you're comparing.
since contains relays on equals implementation, when you do
if(!productListing.contains(s[0]))
you are asking the list OF ARRAYS OF STRINGS if its contains a String.
that will return always false because the type are different, so is not that is working at all, is that your condition will always return false

Java arrays - How to go through List and set specific value

First i add new Popotnik in List popotnik depending on how big it is, which is working fine - function prostaMesta. Then i want to go through list popotnik and set popotnik value depending on where it is in for, but value of i will always be 0 everytime it is being called. Also i have break there as i only want to set one popotnik at the time. How should i increment (i) while having some sort of break in there?
Also if(popotnik.get(i) == null){} is not being called, but values inside popotnik are null(s)
private List<Popotnik> popotnik = new ArrayList<Popotnik>();
public void prostaMesta(List<Popotnik> popotnik, int sedez){
stanovanje.setPostle(sedez);
for(int i=0; i<stanovanje.getPostle(); i++){
popotnik.add(new Popotnik());
}
System.out.println(popotnik);
}
public void dodajPotnika(List<Popotnik> popotnik, Popotnik popotnik2){
for(int i=0; i<popotnik.size(); i++){
if(popotnik.get(i) == null){
setPopotnik(popotnik, i);
popotnik.set(i, popotnik2);
break;
}
}
System.out.println(getPopotnik());
}
public void setPopotnik(List<Popotnik> popotnik, int i){
this.popotnik = popotnik;
}
public List<Popotnik> getPopotnik(){
return popotnik;
}
Main class:
List<Popotnik> alPopotnik = new ArrayList<Popotnik>();
if(x.equals("p")){ //inside of a loop when prostaMesta() is being called
potovanje.prostaMesta(alPopotnik, sedez);
}
`if(x.equals("d")){` //inside of a loop when dodajPotnika() is being called
System.out.println("Vnesi ime: ");
String ime = skener.next();
Popotnik popotnik = new Popotnik(ime);
potovanje.dodajPotnika(alPopotnik, popotnik);
}
The if(popotnik.get(i) == null) is never true because objects on the list are not null. You initialize them in the for loop in prostaMesta.
If you have some fields inside the Popotnik class then they are null, but object itself is not.
You would need to do something like popotnik.get(i).getName() == null.
Besides, if you only want to add a number at the end of popotnik's name then it isn't necessary to initialize a list with empty objects.
You could just add objects to list using a different constructor.
For example popotnik.add(new Popotnik("Popotnik"+(popotnik.size()+1))).
It's not pretty but I think initialization like this here is not necessary.

Returning a different type than the parameter

This is hw and I am really stuck on how to get my code to return what I want it to return. I am trying to return a String value with a given index value. I thought all I had to do was return the string value at the given index but I am not getting the right answer.
public void add(String candidate){
if (candidate.equals(null)){
throw new RuntimeException();
}
String[] contenders = new String[candidates.length+1];
// copy the array manually because I'm restricted from ArrayLists
for (int i = 0; i < candidates.length; i++){
contenders[i] = this.candidates[i];
}
this.candidate = candidate;
contenders[contenders.length-1] = this.candidate;
this.candidates = new String [contenders.length];
After adding values to a newly constructed array the tester wants to get the string value at a given index
public String get(int index){
if (index < 0 || index > candidates.length) {
throw new RuntimeException("Your argument was not within bounds.");
}
for (int i = index; i < candidate.length(); i++){
candidate = candidates[index];
}
return candidate;
I have been working on it and I finally was able to have candidate stop pointing to null it is giving the wrong value for the given index so for example I want 'X' at candidate[3] but I am getting 'Y' because that is the last value that candidate keeps. I have tried just returning candidates[index] but then it tells me that the value at that index is null. As I have gone through the debugger it appears that my original array is not being copied over properly but I am not sure what I should try next. Thanks in advance.
This is my constructor:
public CandidateList(){
candidates = new String[0];
}
public CandidateList(String[] candidates){
this.candidates = new String[candidates.length];
CandidateList candidateList = new CandidateList();
There is a lot that can be improved in your code, let me add some comments
public void add(String candidate){
//if candidate is actually null you are calling null.equals
//which means this will always result in a NullPointerException
//you can remove this if if you want
if (candidate.equals(null)){
throw new RuntimeException();
}
...
//think about what you are doing here,
//you are setting this.candidates to a new empty array
//(is big contenders.length, but still empty)
this.candidates = new String [contenders.length];
Second part:
public String get(int index){
//you are missing an '=' in index >= candidates.length
if (index < 0 || index > candidates.length) {
throw new RuntimeException("Your argument was not within bounds.");
}
//this for loop is wrong, you are changing 'i' but never use it..
//just return candidates[index] like you said before.
//It was probably null because of the error above
for (int i = index; i < candidate.length(); i++){
candidate = candidates[index];
}
return candidate;
A note on the RuntimeException(RE): if you catch a NullPointerException (NPE) and throw a RE you are actually losing information (since NPE is a more specific error rather than RE). If you want to catch/throw put at least a significant message like "candidate cannot be null"
Let's now analyze the constructor:
public CandidateList(){
candidates = new String[0];
}
public CandidateList(String[] candidates){
// you are doing the same error as above here:
// when you do this you create an EMPTY list of size candidates.lenght
// correct code is this.candidates = candidates
this.candidates = new String[candidates.length];
// this is not necessary, constructors don't need to return anything,
//here you are just creating a new instance that will not be used anywhere
CandidateList candidateList = new CandidateList();
Constructors create objects, they don't return data. I suggest you to take a look at this question Does a Java constructor return the Object reference? and in general read a bit more about constructors

Checking if String Array is filled or empty

Hope this is not a duplicate because I already looked up some thread incl. this one, but it didn't help me.
My program is reading in some arguments that are optional by the user. They can add a rule to the game but don't have to.
I know that the rule will be containing 5 Numbers. I wanted to save them in a String Array with 5 spots so I can use them later. If the user won't enter a rule there will be a specific rule taken.
String[] rule = new String[5];
//reading in the program arguments and stuff..
//here I want to check whether the rule is taken from the user or not
//don't want to check with a boolean check
if (rule[0].equals("")) {
String[] newRule = "270-90-315-45-90".split("-");
for (int i = 0; i < newRule.length; i++) {
rule[i] = newRule[i];
}
}
Already tried this:
rule[0].equals("")
rule[0].equals(null)
rule[0].equals("null")
rule[0].matches("")
rule[0].matches("null")
rule.length == 0
rule.equals(null)
But I always get a NullPointerException or the if case will be skipped (length == 0)
Hopeyou can help me.
You didn't have tried the obvious?
if (rule[0] == null) {
Insted of using an fixed array, try using an ArrayList and add the values to the list. The ArrrayList-class will adjust the length of the list automaticly.
Example:
ArrayList<String> rules = new ArrayList<>();
if (rules.size() == 0) {
String[] newRule = "270-90-315-45-90".split("-");
//Instead of newRule.length as a comparison, use the
//number of rules with a number. Or use a foreach-loop
//if the number of rules may vary
for (int i = 0; i < 5; i++) {
rules.add(newRule[i]);
}
}
In the example you provide us with, rule[0] contains the value null which you can see yourself by adding the following line of code:
System.out.println(rule[0]==null);
returns true (try it !)
if (rule[0]==null) {
will return true and get inside the for loop if that is what you want.. See the following class which you can compile (using javac myEmpty.java) and run (using java myEmpty):
class myEmpty {
public static void main(String[] args) {
String[] rule = new String[5];
System.out.println(Arrays.toString(rule));
//reading in the program arguments and stuff..
//here I want to check whether the rule is taken from the user or not
//don't want to check with a boolean check
System.out.println(rule[0] == null);
if (rule[0] == null) {
//if ("".equals(rule[0])) {
String[] newRule = "270-90-315-45-90".split("-");
System.out.println(Arrays.toString(newRule));
for (int i = 0; i < newRule.length; i++) {
rule[i] = newRule[i];
System.out.println(rule[i]);
}
}
}
}
YOUR if if (rule[0].equals("")) { fails simply because rule[0] does not contain the value "" which you are checking for ! Keep in mind that "" and null are not the same, and use your if clauses accordingly !
So you want to change indices entered by user only.
The best way to do this would be to initialize the array with default values, then override those specified by the user.
String[] rule = "270-90-315-45-90".split("-");
// Now read "program arguments and stuff"
The NullPointerException I imagine is coming from the fact you have created an array of strings but have not initialized them with any values. They will default to null if you don't give them a value...hence the NPE.
Depending on where you are getting your input you could do something like this;
private static final String[] DEFAULT_RULES = {"270", "90", "315", "45","90" };
private static String[] rules;
public static void main(String[] args){
if(!isValidRule(args)){
// Potentially also check that the args are digits
throw new IllegalArgumentException("Must contain 5 rules");
}
rules = (args.length > 0) ? args : DEFAULT_RULES; // Used brackets on the ternary operator here for readability. Not essential.
...
}
private static boolean isValidRule(String[] rules){
return rules.length > 0 && rules.length != 5;
}
If you are working with some other non-static method thats taking the input, the same applies. You can perform your string split to get an array based on the delimiter you have specified and then do the same thing.
I don't imagine you would want to be passing around a string containing only hyphens if no rules are passed? Which is what you are hinting at by attempting to check if a string is empty after the split is performed.
Also if you want to check if the string contains characters or not use the isEmpty() method. It returns true if the length is 0 else it returns false. This already achieves what you are needlessly attempting.
In each of your tried options
rule[0].equals("")
rule[0].equals(null)
rule[0].equals("null")
rule[0].matches("")
rule[0].matches("null")
rule.length == 0
rule.equals(null)
You already assumed that your element at 0 index is not null , and calling equals() and matches() method on element at 0th index causing NullPointerException
Thrown when an application attempts to use null in a case where an
object is required. These include:
Calling the instance method of a null object.
Accessing or modifying the field of a null object.
Taking the length of null as if it were an array.
Accessing or modifying the slots of null as if it were an array.
Throwing null as if it were a Throwable value.
Instead try like this
if(rule[0] != null){
// Now you can call methods on your `0th` index element
}

Categories

Resources