Why cant I say variable.array in this case? - java

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;
}
}

Related

Searching an ArrayList for a matching parameter

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());
}
}
}
}

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.

static variables behave differently in maven jars and eclipse runnable jars

I need to use variables initialized in outer class to be used in inner class.So I had used static variables.Also this is Flink application.
When built as eclipse-export-runnable jar --it works fine--state of variable retains
When built as maven or eclipse-export-jar--it fails--state of variable lost
FileMonitorWrapper.fileInputDir--values is "" and don't fetch the passed value.
Sounds strange..any thoughts
static transient String fileInputDir="";
static transient String fileArchiveDir="";
#SuppressWarnings("serial")
public DataStream<String> ScanDirectoryForFile(String inputDir, String inputFilePattern,String archiveDir, StreamExecutionEnvironment env) {
try {
FileMonitorWrapper.fileArchiveDir = archiveDir;
FileMonitorWrapper.fileInputDir = inputDir;
filteredDirFiles = dirFiles.filter(new FileMapper());
.
.
.
}
}
#SuppressWarnings("serial")
static class FileMapper implements FilterFunction<TimestampedFileInputSplit>{
#Override
public boolean filter(TimestampedFileInputSplit value) throws Exception {
if(value.toString().contains("done"))
FileMonitorWrapper.doneFound = true;
if(value.toString().contains("dat"));
FileMonitorWrapper.datFound = true;
if(FileMonitorWrapper.datFound && FileMonitorWrapper.doneFound) {
try {
if(value.getPath().toString().contains("done")) {
Files.move(Paths.get(FileMonitorWrapper.fileInputDir+"\\"+value.getPath().getName()),
Paths.get(FileMonitorWrapper.fileArchiveDir+"\\"+value.getPath().getName()));
}
}catch(Exception e){
e.printStackTrace();
}
return (!value.toString().contains("done"));
}
else
return false;
}
}
}
Generally speaking, serialization of POJOs does not capture the state of static variables. From what I have read about it, Flink serialization is no different.
So when you say that the static variable state is "retained" in some cases, I think you are misinterpreting the evidence. Something else is preserving the state of the static variables OR they are being initialized to the values that happen to be the same in the "before" and "after" cases.
Why am I so sure about this? The issue is that serializing static variables doesn't make much sense. Consider this
public class Cat {
private static List<Cat> allCats = new ArrayList<>();
private String name;
private String colour;
public Cat(...) {
...
allCats.add(this);
}
...
}
Cat fluffy = new Cat("fluffy", ...);
Cat claus = new Cat("claus", ...);
If the static field of Cat is serialized:
Every time a serial stream contains a Cat it will (must) contain all cats created so far.
Whenever I deserialize a stream contains a Cat, I also need to deserialize the ArrayList<Cat>. What do I do with it?
Do I overwrite allCats with it? (And lose track of the other cats?)
Do I throw it away?
Do I try to merge the lists? (How? What semantics? Do I get two cats called "fluffy"?)
Basically, there is no semantic for this scenario that is going to work out well in general. The (universal) solution is to NOT serialize static variables.

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" };
}

Categories