Im doing a little text adventure. Im current working on a inventory. I tried to do my inventory with a list:
ArrayList<Object> inventar = new ArrayList<Object>();
I initialize Objects as Items:
Item holzschwert = new Item("Holzschwert", 1, 5);
inv.addToInventar(holzschwert);
Here's my add Method:
public void addToInventar(Object ...item){
inventar.add(item);
}
But everytime i want to print out my inventory (here's my toString() function) i still get the Hash code:
#Override
public String toString() {
return "Inventar [ Inventar = " + inventar + " ]";
}
and my print method
Object test = inv.getInventar();
String ausgabe = inv.toString();
System.out.println(ausgabe);
and the console log:
Inventar [ Inventar = [[Ljava.lang.Object;#281c35ec] ]
Thank you for your help :)
The mistake is
public void addToInventar(Object ...item){
inventar.add(item);
}
Here item is an Object[], because you used varargs (...). What you are seeing is the result of calling toString on an array.
You want
public void addToInventar(Object item){
inventar.add(item);
}
or possibly
public void addToInventar(Object... items){
for (Object item : items)
inventar.add(item);
}
EDIT
In addition to this answer, I should point out that you should probably not be using List<Object> anyway. List<Item> would be better as mistakes like this are more likely to be spotted by the compiler. The signature addToInventar(Object... items) should really be avoided like the plague, as it will accept literally any sequence of arguments of any length. All reference types are Objects and all primitives can be autoboxed.
Override the Item class toString() method.
class Item{
#override
public String toString(){
//Give your implementation
}
}
#Override
public String toString() {
StringBuffer stuff = new StringBuffer();
for (Object item : inventar) {
stuff.append(item.getName()); // you need a getter for the item name
stuff.append(" ");
}
return stuff.toString();
}
Both your inventory and items are Objects. If you just print the objects and not the fields you will only get their memory address as output:
Ljava.lang.Object;#281c35ec
not the properties you've set up for them.
If you do not care about the exact format of the output, you can do something like this in your Item class:
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
ToStringBuilder is part of the Apache Commons Lang library. If you want it specifically formatted a certain way, then go with #Code Whisperer and write your own implementation.
Related
I have to do a project for my beginners Java class that has to do with inheritance.
The MediaItem class encapsulates the data required to represent a MediaItem. Here is the code that was already given:
public class MediaItem {
protected String title;
protected String author;
protected String genre;
/* Subclasses may add specific parameters to their constructor's
* parameter lists.
*/
public MediaItem(String title, String author, String genre){
this.title = title;
this.author = author;
this.genre = genre;
}
// get method for the title
public String getTitle(){
return title;
}
// get method for the author
public String getAuthor(){
return author;
}
// get method for the genre
public String getGenre(){
return genre;
}
// Subclasses should override.
public String toString(){
return title+", "+author+", "+genre;
}
}
The MediaList class encapsulates a list of media items in a user's collection. The list is implemented as an ArrayList of type MediaList. Each type of media item is represented by an instance of the Book, Movie, Podcast, or Song class. These classes are subclasses of MediaItem. The list stores media items as references of type MediaItem.
Here is the code for adding and removing an item in MediaList:
public void addItem(MediaItem newItem){
itemList.add(newItem);
}
public boolean removeItem(String targetTitle, String targetAuthor){
boolean result = false;
for (MediaItem media : itemList) {
if(itemList.contains(targetTitle) && itemList.contains(targetAuthor)){
itemList.remove(media);
result = true;
} else {
result = false;
}
}
return result;
}
When this test runs with Junit, an error is thrown saying there expected size was <1> but it should be <0>
When I run it and answer the prompts, it says the media item is added but when I try to remove the media item it says "Could not find Black Panther in the library, nothing removed."
#Test
public void addOneRemoveOneItemUpdateSizeTest() {
MediaItem item = new Movie("Black Panther", "Coogler", "fantasy", 134, "Chadwick Boseman", "2018");
mediaList.addItem(item);
mediaList.removeItem("Black Panther", "Coogler");
int studentSize = mediaList.getNumItems();
assertEquals("Test 30: Add item, remove item size is 0.", 0, studentSize);
Movie class
public class Movie extends MediaItem {
public Movie(String title, String author, String genre,
int playTime, String leadActor, String releaseYear){
super(title, author, genre);
playTime = 0;
leadActor = "noLead";
releaseYear = "noRelease";
}
public int getPlayTime(){
return playTime;
}
public String getLeadActor(){
return leadActor;
}
public String getReleaseYear(){
return releaseYear;
}
#Override
public String toString(){
super.toString();
return "Movie: " + title + ", " + author + ", " + genre + ", " + playTime + ", " + leadActor + ", " + releaseYear;
}
}
Is my removeItem method wrong? I don't understand why the title can't be found. Can someone point me in the right direction?
I think the problem is this if statement:
if(itemList.contains(targetTitle) && itemList.contains(targetAuthor)){
It should be
if (media.getTitle().equals(targetTitle) && media.getAuthor().equals(targetAuthor))
In other words, you need to check whether each media item, rather than the list, has the right title and author.
There are two correction points for this code:-
The conditional statement is not correct
Deletion is being done incorrectly & it will lead to ConcurrentModification Exception
1. Conditional Statement Bug Explanation
The contains() method checks for the existence of passed object in the list. It is handy while dealing with wrapper classes or String class but whenever we have our custom data types such as classes and use case demands to remove the object on the basis of certain properties then this method may not be helpful.
Right now your code is checking for the String objects in your arguments 'targetTitle' and 'targetAuthor' and thus fail to remove the desired object from your list.
Your use case demands the removal of object from list on the basis of 'title' and 'author' which are the properties(instance variables) of MediaItem class and hence when you are traversing through all the objects in the list you should check the respective instance variables of the objects that you are traversing in the List.
Kindly use '==' instead of equals() method as you will have to do explicit null checks otherwise you can end up having NullPointer exception.
2. Incorrect Deletion from List
You are making the modification on the same object which you are traversing via for-each(Enhanced for) loop. You should make use of iterator object for this purpose. Please go through this link for further information.Using iterator for deleting elements in collection
I think you are removing item in the wrong way. You should remove item from list by using iterator or loop from the end of list.
Futhermore, the conditional statements is wrong too, you should use String.equals to check item's attributes that match inputs. In addition, you ought to validate input to prevent Null Pointer Exception.
I'm new to Java and I'm trying to get my head around constructs, classes and objects. I apologise if any of this seems stupid to you.
I have been tasked with creating an ArrayList to hold items of type Data (my class). using the .add method - I should add a certain number of names and ages then output.
I have sort of done it, but I was wondering if I could use the functions like SetAge and SetAge from my class to use within my ArrayList to create a new person and then output it together like I have with the rest. Is there another way?
Thank you for your help & explanation.
Below is my code;
import java.util.ArrayList;
public class workingOn {
public static void main (String[] args)
{
Data Fred = new Data("Fred", 21);
Data Jo = new Data("Jo", 43);
Data Zoe = new Data("Zoe", 37);
ArrayList<Data> myArray = new ArrayList<Data>();
myArray.add(Fred);
myArray.add(Jo);
myArray.add(Zoe);
for (Data temp : myArray)
{
System.out.println(temp.toString());
}
}
}
Below is my class;
public class Data {
private String name;
private int age;
Data(String n,int a)
{
name = n;
age = a;
}
public String GetName()
{
return(name);
}
public void SetName(String n)
{
name = n;
}
public int GetAge()
{
return(age);
}
public void SetAge(int a)
{
age = a;
}
public void Print()
{
System.out.print(("("+ GetName() ));
System.out.print(",");
System.out.print(GetAge());
System.out.print(") ");
}
//i made this so I don't output the object id
public String toString() {
return (name + ", " + age);
}
}
Going through the comments, I am guessing you want to somehow use the setter methods (setName() and setAge()) for the class that you have designed. The easiest way would be:
Data d = new Data("tempName", 10);
myArray.add(d);
This basically creates an object of type Data and adds it to the arraylist. Let's assume that you want to change the name and age of this person you just added, then you should do this:
myArray.get(myArray.size() - 1).setName("newName");
myArray.get(myArray.size() - 1).setAge(18);
To add some explanation, when you add an object to an arraylist, it always adds in the end. We use size() method to get the number of objects in the Arraylist. Since index starts from 0, we use myArray.size() - 1. We use the .get() method to retrieve the object from the arraylist which takes a number as a parameter and return the object at that index.
Combining these two, we get the object at the last possible index, and call the setName() and setAge() function on it.
Hope this helps.
I have written below code to print the Search objects in the groups map. But I am not getting the correct output.
Mycode:
Map<Integer, List<Search>> groups = group.stream().collect( Collectors.groupingBy( w -> w.getId()) );
System.out.println( groups );
Output I get:
{
1=[Models.Search#30269b0d],
2=[Models.Search#423e11a8],
3=[Models.Search#25e2f879]
}
I want my output to print the grouped Search objects. Please help.
Edited:
sample output I want
{
1=[Michael/14/UK/90, Tim/15/UK/91, George/14/UK/98],
2=[Jan/13/POLAND/92, Anna/15/POLAND/95],
3=[Helga/14/GERMANY/93, Leon/14/GERMANY/97]
}
Override the toString() method in Search class and return your custom String based on the fields that you want to have in the output. What you see here is simply the objects reference.
Edit for sake of completeness:
#Override
public String toString() {
return res=name+"/"+someNumber+"/"+country+"/"+someOtherNumber;
}
In your class Search,override toString like
#Override
public String toString() {
String res=value1+"/"+value2+"/"+...
return res;
}
I want to make a program where you can name a String("weapon" for example)and then add that String to a ArrayList. But without typing it yourself like:
MyArrayList.add(Egg); //for example
So that the new Object automatically add to the Arraylist.
So what I did, I created an Arraylist that will hold the weapon names. I made a method, where you can "make" in the main class a object with the weapon name.But how do i make something that when a object (in the main class)is created, it automatically add it self to the arraylist.
(Sorry for bad explaining, I'm from The Netherlands so... If it's a bad explaining please tell me so i can improve it)
Maybe I completely misunderstand it, but do you want to do something like this?
private ArrayList<YourObject> list;
public YourMainClass(){
list = new ArrayList<YourObject>();
}
public void onAdd(String weaponName){
list.add(new YourObject("weaponName")); // <- this being your issue
}
With YourObject being something like:
public class YourObject
{
private String name;
public YourObject(String n){
setName(n);
}
public void setName(String n){
// Perhaps an if-else to check if n isn't null, nor emtpy?
name = n;
}
public String getName(){
return name;
}
}
Based on my interpretation of your problem, you want to have the user create a weapon name and add it to the ArrayList without having to manually add the code to add it?
A basic way to get String input from a user:
Scanner inputscan = new Scanner(System.in); //reads input from command line
String weapon = inputscan.nextLine(); //waits for user input
MyList.add(weapon);
That way, every time you call the "make" method with that code in it, it will prompt the user to type a weapon name, then the weapon name gets stored in the array.
I think you want to initialize the List with an object in it:
Try using an instance block, like this:
List<String> list = new ArrayList<String>() {{
add("Egg");
}};
Add the command to add the object to the collection in the constructor.( But this ill advise)
You can create an auxiliary class that will create that object and label to the collection.
class WeaponFactory
{
Collection c;
public WeaponFactory(Collection coll){c=coll;}
public Weapon makeWeapon(String text) // Makes sense when the object is not String , like a Weapon class which also contains stats or something
{
Weapon w = new Weapon(text)
c.add(w);
return w;
}
}
class Weapon
{
String name;
public Weapon(String text)
{
name = text;
}
}
I'm working on a special pathfinding system in java, which needs to print it's path at one point. It's far from done but I ran into a problem. When I run my code it instead prints a pointer towards an string rather then the string itself. Here is the code:
public class node {
int optionnum;
node[] options;
String[] dirrections;
String[] route;
boolean[] visited;
public node(){
options= new node[4];
dirrections= new String[4];
route= new String[50];
for (int i=0;i<50;i++){
route[i]="";
}
visited= new boolean[50];
}
public void revmdp(int num){
visited[num]=true;
for(int i=0;i<optionnum;i++){
System.out.println(options[i].route[0]); //how can this be a pointer?
options[i].revmdp(dirrections[i],num);
}
public void revmdp(String nroute, int num){
//System.out.println(route[0]+dirrections[0]);
if (!visited[num]||nroute.length()<route[num].length()){
route[num]=nroute;
visited[num]=true;
for(int i=0;i<optionnum;i++){
options[i].revmdp(route+dirrections[i],num);
}
}
}
}
output looks like this
[Ljava.lang.String;#2d66a22b3;
As you can see in the constructor of path I already set the path towards the string "" (empty string). As the string is not yet changed any futher at moment this code is called I would expect it to return "" however it instead gives these weird string pointers. Anybody know what's up?
Note I have already tried to call route[0][0] but java won't allow that.
Update 3: I found it.
options[i].revmdp(route+dirrections[i],num);
Here you are doing string concatenation on an array and a String. This causes to set route[num] in the level of recursion to this concat result.
Each Java class inerhits from the class Object, which implements the default toString() method. The Source code of the default toString() Method looks like :
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
If you do not override the default toString() method, the method above is called.