Searching an ArrayList for a matching parameter - java

I have two classes Museum and Painting. Painting class is working as expected, but I am having issues with the Museum class. The purpose of the method is to return an ArrayList of paintings the museum has, which matches the parameter string.
When I try to compile the code, I am getting lots of error messages and clearly I am not compiling the code correctly.
For example, if there is a Painting by Picasso - it should just return all those paintings and nothing else.
I think I may have missed a step - potentially by creating a local variable to store it in first, but I'm at a bit of a brick wall. I also wonder if String is correct when the ArrayList uses the Painting object.
Does anyone know what I'm missing here?
public class Museum {
//creating the fields
private ArrayList<Painting> paintings;
private String name;
/**
* Create a Museum Class
*/
public Museum(String aMuseum) {
paintings = new ArrayList<>();
name = aMuseum;
}
public String listMatches(String searchString)
{
if(filename.equals(searchString)) {
return filename;
}
}
}

Searching paintings by artist should return a sublist of paintings (it may be empty if no painting is found):
public List<Painting> listMatches(String artist) {
List<Painting> matches = new ArrayList<>();
for (Painting painting : paintings) {
if (artist.equals(painting.getArtist())) {
matches.add(painting);
}
}
return matches;
}
Stream API may be used for this (more concise and functional style):
public List<Painting> listMatches(String artist) {
return paintings.stream()
.filter(p -> artist.equals(p.getArtist()))
.collect(Collectors.toList());
}

Okay I'm assuming here in your Painting class, you have an attribute which is Author and a getter for it.
I've changed the listMatches method to have a for-each loop. This loop will go through every element in your Paintings arraylist, and saving in a local variable the name of its author. If the current painting's author matches the one you are looking for, it will print the title.
I changed the return type of listMatches from String to void, because you are not returning anything, just printing.
Instead of just printing the names you could save the paintings somewhere (another ArrayList for example) if you want to use them. Remember to change the return type, because in that case you will be returning something.
Remember to write the name of the author exactly as you have it in the paintings or else it might not find it.
I havent had a chance to try it, but it should work.
public class Museum {
//creating the fields
private ArrayList<Painting> paintings;
private String name;
/**
* Create a Museum Class
*/
public Museum(String aMuseum) {
paintings = new ArrayList<>();
name = aMuseum;
}
public void listMatches(String searchString)
{
String this_painting_author = new String();
for (Painting painting : paintings){
this_painting_author = painting.getAuthor();
if(this_painting_author.equals(searchString)) {
System.out.println(painting.getTitle());
}
}
}
}

Related

How to make code dynamic for similar kind of blocks

I am creating my web page with vaadin where I need to create same kind of blocks for different type for example need to show blocks having car details, so only car name would be different but the block design would be same with same label but different labels. I want to write generic code so that i can expand it for any car name, without adding it manually.
Attaching the code snippet which i am using where i am repeating my code for different type. Want to implement it dynamically.
private Grid<PresentableGenerateInputHeaders> winTSHeaderColumnsGrid;
private Grid<PresentableGenerateInputHeaders> fRHeaderColumnsGrid;
private ListDataProvider<PresentableGenerateInputHeaders> listDataProvider;
private List<PresentableGenerateInputHeaders> presentableGenerateInputHeaders = new ArrayList<>();
private void initWinTsGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
winTSHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
winTSHeaderColumnsGrid.setDataProvider(listDataProvider);
winTSHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
winTSHeaderColumnsGrid.setStyleName("a-units");
winTSHeaderColumnsGrid.setWidth("450px");
winTSHeaderColumnsGrid.setItems(addGridValues(DataSource.WIN_TS, winTSHeaderColumnsGrid));
winTSHeaderColumnsGrid.getEditor().setEnabled(true);
winTSHeaderColumnsGrid.setColumnOrder("header", "count");
winTSHeaderColumnsGrid.sort("header");
winTSHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountWINTS.add(event.getBean());
});
}
private void initFRGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
fRHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
fRHeaderColumnsGrid.setDataProvider(listDataProvider);
fRHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
fRHeaderColumnsGrid.setStyleName("a-units");
fRHeaderColumnsGrid.setWidth("450px");
fRHeaderColumnsGrid.setItems(addGridValues(DataSource.FR, fRHeaderColumnsGrid));
fRHeaderColumnsGrid.getEditor().setEnabled(true);
fRHeaderColumnsGrid.setColumnOrder("header", "count");
fRHeaderColumnsGrid.sort("header");
fRHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountFR.add(event.getBean());
});
}
You can change methods to be more generic by identifying all the parts you don't want to keep static, and moving those to be populated by method parameters instead. I.e. instead of
private void myMethod() {
grid.setCaption("myCaption");
}
you would write
private void myMethod(String caption) {
grid.setCaption(caption);
}
and then call it
myMethod("myCaption");
If you need to be outside of the whole class to be able to determine what the real values are, you can for example make the method public or pass on the necessary values in the class constructor.
public MyClass(String gridCaption) {
myMethod(gridCaption);
}
If there are a lot of values you need to set dynamically, you might consider using an object that contains all the necessary values instead.
public void myMethod(MyPojo pojo) {
grid.setCaption(pojo.getGridCaption());
}
In your example it looks like the generic values you want to pass are DataSource dataSource and whatever type of collection selectedGapFillingCountWINTS and selectedGapFillingCountFR happen to be, and the method should probably return the grid rather than set it directly to a class variable.

Putting methods that handle HashMap of all instances of a class in a separate class

I have a class that creates index cards, and within it, I have an instance variable that is a static HashMap that stores all the instances created.
I have been thinking a lot about it and I thought that the methods that handle the opperations over that HashMap should go in a different class, because those methods don't opperate directly over any index card, they opperate over the list of index cards.
This way, I would have an IndexCard class, and an ListAdministrator class. And both classes would handle different functions.
The problem is that this new class (ListAdministrator) would only have static methods, because there is only one list and there is no reason to create any new list of index cards, I only need one.
Should I move those methods to another class or should I keep it like this? Is that a good practice?
This is the code:
class IndexCard {
public static HashMap <String, IndexCard> list = new HashMap <> ();
public String name;
public String address;
public String phone;
public String email;
public LocalDate dateRegister;
IndexCard(String name, String dni, String address, String phone, String email) {
this.name = name;
this.address = address;
this.phone = phone;
this.email = email;
dateRegister = LocalDate.now();
if (Utils.validarDni(dni) && !list.containsKey(dni)) {
list.put(dni, this);
} else {
throw new InvalidParameterException ("Error when entering the data or the DNI has already been previously registered");
}
}
/**
* Update the data of the selected card.
*/
public void update() throws IllegalAccessException {
String key = getKeyWithObject(this);
Scanner reader = new Scanner(System.in);
Field[] fields = this.getClass().getFields();
for (Field field: fields) {
String nameField = Utils.splitCamelCase(field.getName());
if (!Modifier.isStatic(field.getModifiers()) && (field.getType()).equals(String.class)) {
System.out.println ("Enter new " + nameField);
String value = reader.nextLine().trim();
field.set(this, value);
}
}
reader.close();
list.put(key, this);
System.out.println("Updated data \n \n");
}
/**
* Delete the selected card.
*/
public void delete() throws IllegalAccessException {
String key = getKeyWithObject(this);
Field [] fields = this.getClass().getFields();
for (Field field: fields) {
if (!Modifier.isStatic(field.getModifiers())) {
field.set(this, null);
}
}
list.remove(key);
}
/**
* Displays the data of the selected card on screen.
*/
public void print() throws IllegalAccessException {
Field [] fields = this.getClass().getFields();
for (Field field: fields) {
if (!Modifier.isStatic(field.getModifiers())) {
String nameFieldConSpaces = Utils.splitCamelCase(field.getName());
Object value = field.get(this);
System.out.println(nameFieldConSpaces + ":" + value);
}
}
}
/**
* Print all the entries of the desired sublist with the ID, Name and phone number.
*/
public static <T extends IndexCard> void SubClasslist (Class <T> subClass) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
String key = entry.getKey ();
IndexCard card = entry.getValue ();
if (card.getClass().equals(subClass)) {
System.out.println ("ID:" + key + "| Name:" + card.name + "| Phone:" + card.phone);
}
}
}
/**
* Returns the object stored in the list of cards when entering the corresponding key.
*/
public static IndexCard GetObjetWithKey(String key) {
try {
return list.get(key);
} catch (IllegalArgumentException e) {
System.out.println (e + ": The indicated key does not appear in the database.");
return null;
}
}
/**
* Obtain the Key when entering the corresponding card.
*/
public static String getKeyWithObject (Object obj) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet()) {
if (obj.equals(entry.getValue())) {
return entry.getKey();
}
}
throw new IllegalArgumentException ("The indicated data does not appear in the database, and therefore we could not obtain the key.");
}
/**
* Returns a list of cards when entering the main data of the card.
* #param data Corresponds to the identifying name of the file.
*/
public static ArrayList <IndexCard> SearchByName (String data) {
try {
ArrayList <IndexCard> listCards = new ArrayList <> ();
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
IndexCard card = entry.getValue ();
String name = entry.getValue().name;
if (name.toLowerCase().trim().contains(data.toLowerCase().trim())) {
listCards.add(card);
}
}
return listCards;
} catch (IllegalArgumentException e) {
System.out.println (e + "The indicated data does not appear in the database, you may have entered it incorrectly.");
return null;
}
}
}
All those static methods are what I would put in the new class.
This is how the new class ListAdministrator would look. It would not even need a constructor.
class ListAdministrator{
public static HashMap <String, IndexCard> list = new HashMap <> ();
/**
* Print all the entries of the desired sublist with the ID, Name and phone number.
*/
public static <T extends IndexCard> void SubClasslist (Class <T> subClass) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
String key = entry.getKey ();
IndexCard card = entry.getValue ();
if (card.getClass().equals(subClass)) {
System.out.println ("ID:" + key + "| Name:" + card.name + "| Phone:" + card.phone);
}
}
}
/**
* Returns the object stored in the list of cards when entering the corresponding key.
*/
public static IndexCard GetObjetWithKey(String key) {
try {
return list.get(key);
} catch (IllegalArgumentException e) {
System.out.println (e + ": The indicated key does not appear in the database.");
return null;
}
}
/**
* Obtain the Key when entering the corresponding card.
*/
public static String getKeyWithObject (Object obj) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet()) {
if (obj.equals(entry.getValue())) {
return entry.getKey();
}
}
throw new IllegalArgumentException ("The indicated data does not appear in the database, and therefore we could not obtain the key.");
}
/**
* Returns a list of cards when entering the main data of the card.
* #param data Corresponds to the identifying name of the file.
*/
public static ArrayList <IndexCard> SearchByName (String data) {
try {
ArrayList <IndexCard> listCards = new ArrayList <> ();
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
IndexCard card = entry.getValue ();
String name = entry.getValue().name;
if (name.toLowerCase().trim().contains(data.toLowerCase().trim())) {
listCards.add(card);
}
}
return listCards;
} catch (IllegalArgumentException e) {
System.out.println (e + "The indicated data does not appear in the database, you may have entered it incorrectly.");
return null;
}
}
}
You should keep the concerns of managing the IndexCards and the IndexCards themselves separate because of the Single Responsibility Principle. Furthermore the ListAdministrator should handle everything that deals with the management of the IndexCards, also deletion and creation of the managed objects.
The name ListAdministrator is somehow not meeting the point as it does not administrate lists, maybe use something like IndexCardRegistry.
To deal with concurrency you could use a ConcurrentMap as your main data storage.
Having ListAdministrator all static might come in handy if your IndexCards need access to it or other IndexCards, but this would not be the best design. Do they need to know anyway? From my understanding the IndexCards could be simple POJOs that contain only data and no logic at all.
On the other hand with an all-static ListAdministrator you will not be able to use two instances of managed objects at the same time in the future without major refactoring your code. Even if you never would expect this today a well defined object registry that can handle any object might come in handy in projects to come. Therefore I would rather use real instances for the ListAdministrator (and program against it's interface to stay flexible).
In more detail referring to your comments:
The idea of this approach is to keep concerns clearly separated, which will make future changes to your code feasible in case the project grows (most projects tend to do so). My understanding is that the ListAdministrator should manage your IndexCards. In a way this is the same as Object Relational Mappers work, but at the moment your database is a HashMap. If you create an interface for ListAdministrator you may even swap out the HashMap with a database without having to change its clients.
On second investigation of your code I found that IndexCards not only store the data but as well have methods to update the data. This represents another break of the Single Responsibility Principle and should be dealt with. If the ListAdministrator would provide an update method for a given IndexCard it could be used by as many different clients you can think of without changing any code behind the ListAdministrators API. Your first client would be the command-line interface you already have programmed, the next might be a web service.
With an all-static ListAdministrator you have one static Class that manages one static data set. It will always only deal with IndexCards, everything you add will end up in the same HashMap (if allowed/compatible). Every part of your application with access to the class ListAdministrator would have full access to the data. If you needed another ListAdministrator (handling create, delete, update, search) for a different type you would have to refactor everything to accomodate this or start duplicating code. Why not create an instance based solution in the first place. You would have your repository for IndexCards, and could add new repositories at will.
Maybe this is over-engineering for your use case but in keeping the responsibilities clearly separated you will find out that many extensions of your code will happen orthogonal (not affecting existing code), and this is where the fun really begins. And how do you want to practice this if not with smaller projects.
More details about the reason of using interfaces for flexible code (in response to latest comment)
The short answer is: always code against an interface (as stated in numerous articles and java books). But why?
A Java interface is like a contract between a class and its clients. It defines some methods, but does not implement them itself. To implement an interface you define a class with class XYZ implements SomeInterface and the source code of the class does whatever it finds reasonable to answer to the methods defined in the interface. You try to keep the interface small, to contain only the essential methods because the smaller the interface is, the less methods you have to take into account when changes have to be made.
A common idiom in Java would be to define a List<T> return type (the interface) for a method, which most likely would be an ArrayList (concrete class), but could be a LinkedList (another concrete class) as well, or anything else that implements the List interface. By just returning the List interface you prevent your client to use other methods of the otherwise returned concrete class as well which would greatly reduce your freedom to change the internal implementation of your "ListProvider". You hide the internal implementation but agree to return something that fulfills the given interface. If you want to conceed to even less obligations, you could return the interface Iteratable instead of List.
Checkout the Java API, you will find standard classes like ArrayList implement many interfaces. You could always use an ArrayList internally and return it as the smallest interface possible to do the job.
Back to your project. It would be essential to refer to the Registry (ListAdministrator) via its interface, not its concrete class. The interface would define methods like
interface IndexCardRegistry {
void delete(Long id) throws IllegalAccessException;
void update(Long id, Some data) throws IllegalAccessException;
// ...
}
What it does is of no concern for the client, it just hopes everything goes right. So if a client calls the repositories update method it would rely on the repository to update the targeted IndexCard. The repository could store the data as it wants, in a HashMap, in a List or even in a database, it would not matter to the clients.
class IndexCardMapBasedRegistry implements IndexCardRegistry {
private Map store = new HashMap();
void delete(Long id) throws IllegalAccessException {
// code to remove the IndexCard with id from the hashmap
}
void update(Long id, Some data) throws IllegalAccessException {
// code to get the IndexCard with id from
// the hashmap and update its contents
}
// ...
}
Now the new iteration, at creation of your registry you swap out IndexCardMapBasedRegistry for the new
class IndexCardDatabaseRegistry implements IndexCardRegistry {
private Database db;
void delete(Long id) throws IllegalAccessException {
// code to remove the IndexCard with id from the database
}
void update(Long id, Some data) throws IllegalAccessException {
// code to update the IndexCard with id in the database
}
// ...
}
IndexCardRegistry indexCards = new IndexCardMapBasedRegistry(); becomes
IndexCardRegistry indexCards = new IndexCardDatabaseRegistry();
The client must not change at all, but the Registry would be able to handle an amount of IndexCards that otherwise would blow your computers memory.
Stay with IndexCard class and dont need to create new class ListAdministrator
In class IndexCard you have list as of type hashmap and it represent in memory data structure and you have n number of method in this class to work in this data structure so i suggest stay with single class as it will serve single responsibility.

Java converting from Object to Subclass

Here is my code for Scene.java. It has different types of objects, all of which are included in one common ArrayList called targets. All of them share a toString() method that returns their identifier. I want to use the targets list to determine if there is any object in the scene that matches a given identifier, regardless of its type:
ArrayList<NPC> npcs = new ArrayList<NPC>();
ArrayList<Item> items = new ArrayList<Item>();
ArrayList<EnviromentalObject> enviromental_objects = new ArrayList<EnviromentalObject>();
ArrayList<Object> targets;
public Object check_for_target(String target_name){
targets.addAll(npcs);
targets.addAll(items);
targets.addAll(enviromental_objects);
for (Object target : targets){
if (target.toString() == target_name){
return target;
}
}
return null;
Here is the code in Game.java, which checks for a given identifier. If there is a match ion the current scene, I want to know the object's type and treat it as its true type. Right now, I have the following code, and I knew it wouldn't work, but maybe it'll help get my idea across.
Object target = current_scene.check_for_target(target_name);
if (target == null){
System.out.println(UNRECOGNIZED_TARGET_MESSAGE);
} else {
String target_type = target.getClass().getName();
target = (target_type) target;
}
What would be the correct way of getting the object's type and then being able to use that object's methods? Right now, I'm only given Object's methods. Do I create a superclass for NPC, Item, and EnviromentalObject?
Basically, you can check if an object is an instance of a specific class.
it could be something like this :
if( target instanceof NPC) {
System.out.println("target is a NPC");
}
else if( Target instanceof Item) {
System.out.println("target is an Item");
}
if( target instanceof EnviromentalObject) {
System.out.println("target is EnviromentalObject");
}
Edit: as we talked in the comments I think you can change your code to reach a better solution. The above code is still works but it can be a very good practice to using Design Patterns that are known as best practices in programming. For this situation think about using java interface and define share methods that each object could implements them by its need. In the simplest way they print their identifier. Let's use an example :
public interface SceneThings() {
public void printIdentifire();
public String doSomeOtherThings();
}
Each object can implements the above interface by it needs like :
public class Item implements SceneThing {
...
public void printIdentifire(){
//print its identifier here.
System.out.print("ID:ITEM###");
}
public String doSomeOtherThings(){
//do some other works !!!
}
...
}
for other items same as above. And then you can use a single array to keep them without worry about their origin class like this:
ArrayList<SceneThings> targets = new ...
SceneThing obj = new Item();
targets.add(obj);
I hope this can help you to define a better solution in your case.
One of the ways how it could be done it to declare a superclass or interface Target and use it to keep targets array, the full code sample with abstract class:
ArrayList<NPC> npcs = new ArrayList<NPC>();
ArrayList<Item> items = new ArrayList<Item>();
ArrayList<EnviromentalObject> enviromental_objects = new ArrayList<EnviromentalObject>();
ArrayList<Target> targets;
public Target check_for_target(String target_name) {
targets.addAll(npcs);
targets.addAll(items);
targets.addAll(enviromental_objects);
for (Target target : targets) {
if (target.toString().equals(target_name)) {
return target;
}
}
return null;
}
private abstract class Target {}
private class NPC extends Target {}
private class Item extends Target {}
private class EnviromentalObject extends Target {}

How can I reference / define an array from another method in java?

I have some code that is similar to the following:
public class exampleClass {
public void main(){
defineVariable();
nextMethod();
}
void nextMethod(){
list[8] = "threw away";
}
void defineVariable(){
String[] list = {"trivial string","more trivial strings",
"just another trivial string","tr","a","sd",
"godzilla","ate","my","pony","and homework","trivial"};
}
}
And I cant access list in nextMethod.How can I fix this problem , it may seem trivial to make such a small array global but the actual arrays are in the hundreds (hence the fact I didnt c+p my actual code although if this is necessary I wont mind in the least).
Thanks very much and as a side note this is in Android although I doubt that that will effect the java code (am I wrong to assume this?).
Anyway thanks again! Ive been using StackOverflow alot lately and have only contributed a bit so from now on I will attempt to answer as many questions as I can.
Thanks,
Simply declare it in class.
public class exampleClass {
public void main()
{
nextMethod(defineVariable());
}
void nextMethod(String[] list)
{
list[8] = "threw away";
}
private String tab[] defineVariable()
{
String[] list= {"trivial string","more trivial strings","just another trivial string","tr","a","sd",
"godzilla","ate","my","pony","and homework","trivial"};
return list
}
}
If you let defineVariable be void and create a variable within its own scope, that variable just disappears into oblivion upon finished exection. Instead, have defineVariable return the list and then use this list as a parameter to the nextMethod() function.
A neat way to store many variables is to group them into different objects.
That way variables that are related can be put into the same object and the number of variables in your main class is reduced to a managable number.
In the example below, I have made the variables public. If you prefer, you can create getters and setters instead.
public class Actions {
public String humans[] = { "sit", "stand", "eat", "walk", "run", "drive", ride" };
public String dogs[] = { "sit", "stand", "bark", "run" };
public String sharks[] = { "swim", "attack" };
}
public class Equipment {
public String armour[] = { "leather", "chainmail", "plate" };
public String weapon[] = { "sword", "axe", "dagger" };
}

Why cant I say variable.array in this case?

I don't see why I cant do this, without getting an error saying "Songs cannot be resolved or is not a field". I am a noob by the way, trying to learn this stuff :) Thanks in advance for you time, and please tell me if you need more information.
import java.util.ArrayList;
public class Band {
public String bandName;
public ArrayList<String> musician = new ArrayList<String>();
public ArrayList<String> songs = new ArrayList<String>();
// Constructor
public Band(String bandName) {
this.bandName = bandName;
}
public void getBandSongs(String bandName){
for (String s : bandName.songs) { <<<<<<<<<<<ERROR HERE
String rating = s.substring(0,1);
s = s.substring(1);
System.out.println("Rating: " + rating + " - Song name: " + s);
}
}
}
Sometimes the errors that the IDE gives you are misleading, but this one is quite clear.
So, let's analyse it:
"Songs cannot be resolved or is not a field"
So that should ring up an alarm. First thing you should do is look at the type that is your variable bandName.
public void getBandSongs(String bandName){
for (String s : bandName.songs) ...
It's a String! Of course you won't be able to access a field "songs" of a type String.
Maybe in your method signature you meant to have the following:
public void getBandSongs(Band band)
In that case, you should be able to access band.songs just fine.
Or you could have meant the following:
for (String s : this.songs)
That means you would be accessing the "songs" variable of the object instantiation of the class Band.
In summary:
The attributes that you define in your class:
public String bandName;
public ArrayList<String> musician = new ArrayList<String>();
public ArrayList<String> songs = new ArrayList<String>();
can be accessed through a variable that is of type of that class (in this case Band).
Hope this has made it a bit clear. Are you following any book in particular? I recommend the O'Reilly series. Good luck!
ps: I don't want to add too much since you are starting. But I advise you to read up on "encapsulation". That means that, unless strictly necessary, your should, by default, make your class's arguments private and let other classes access them through "getters" and "setters". Such that:
public class Band {
private String bandName;
private ArrayList<String> musician = new ArrayList<String>();
private ArrayList<String> songs = new ArrayList<String>();
public String getBandName(){
return this.bandName;
}
public void setBandName(String bandName){
this.bandName = bandName;
}
//And like that for the other two attributes. That way the classes that need access
// to these will either use a "get" method or a "set" method without directly
// accessing the attributes.
}
The work of creating getters and setters is so redundant that both Eclipse and Netbeans IDEs have a functionality that allows you to do these automatically.
songs is a part of Band, not bandName.
use this.songs instead (or just songs).
It should be noted though that public fields are against encapsulation (and thus OOP). Is this really what you want?
The major benefit of encapsulation (providing getters & setters for instance members) is to have a unified way of accessing your fields in a class. This allows you to, for example, add validation logic to your data.
private List<String> songs = new ArrayList<>();
public List<String> getSongs(){
return songs;
}
public List<String> setSongs(List<String> songlist) {
this.songs = songlist;
}
Now you can add validation to these methods. For example if you want to make sure you can only set the songlist if it has at least 5 songs in it:
public List<String> setSongs(List<String> songlist) {
if(songlist.size() > 5) {
this.songs = songlist;
}
}

Categories