This question already has answers here:
java ArrayList contains different objects
(5 answers)
Closed 6 years ago.
I have an abstract class with several subclasses. A tester class has an ArrayList with 1 object of each subclass in it. They each have a method of the same name, how can I iterate through the ArrayList and call that method for each object?
One of my subclasses (others basically the same):
public class MyMath extends Homework {
private int pagesRead;
private String typeHomework;
public MyMath(int pagesRead, String typeHomework) {
super(pagesRead, typeHomework);
}
public void createAssignment(int p) {
setPagesRead(p);
setTypeHomework(typeHomework);
}
public void toString(int pagesRead, String typeHomework) {
System.out.println("Homework type: " + typeHomework + ". Number of pages read: " + pagesRead + ".");
}
}
In my tester class main method:
ArrayList homework = new ArrayList();
homework.add(new MyMath(5, "Math"));
homework.add(new MyScience(5, "Science"));
homework.add(new MyEnglish(5, "English"));
homework.add(new MyJava(5, "Java"));
Well, if the method is specified in your abstract class, and you have already built the ArrayList with all the objects inside it, you should simply be able to iterate through the ArrayList (for-loop) and just call the .method()
If your ArrayList is of type and your interface also has the method then you can call them like so
for(int i = 0; i < list.length();i++)
{
list[i].METHOD_NAME();
}
You can iterate through the arraylist ant it contains objects and you can call the method on that object. for example,
ArrayList<AbstractClass1> objs = new ArrayList<AbstractClass1>();
objs.add(); // you have added objects already.
Then
for(int i = 0; i< objs.size() ; i++){
objs.get(i).methodYouDefined();
}
If you haven't covered generics yet in class, you have to cast manually. If you have covered generics, you should use them! See lak91's answer.
public abstract class AbstractTest
{
public abstract void oneTwo( int i, String s );
public static void main(String[] args) {
List list = new ArrayList();
list.add( new One() );
list.add( new Two() );
for( Object test : list ) {
AbstractTest abTest = (AbstractTest) test;
abTest.oneTwo( 0, "test" );
}
}
}
class One extends AbstractTest {
#Override
public void oneTwo( int i, String s )
{
System.out.println("One");
}
}
class Two extends AbstractTest {
#Override
public void oneTwo( int i, String s )
{
System.out.println("Two");
}
}
Related
I've got:
interface - ISpacecraft
abstract class - Spacecraft (implements the interface above)
Classes - 4 Kind of ships (derived children of Spacecraft)
Task: Return the count of every ship, if I have 2 cargoShips, then return 2.
Problem: When I iterate through the ArrayList It prints '2' twice, because I have 2 cargoShips.
Expected output: 2,1,1,2
Current output: 2,2,1,1,2,2
Question: How can I iterate through the number of types of ships, instead of all instances of them?
Note: I can't change the signature of 'printInstanceNumberPerClass'.
Code:
StarFleetManagerTester
public static void printInstanceNumberPerClass (ArrayList<ISpacecraft> fleet)
{
ArrayList<ISpacecraft> objects = new ArrayList<>(fleet);
ArrayList<Integer> cnt = new ArrayList<Integer>();
for(ISpacecraft obj : objects)
{
cnt.add(obj.getCount());
}
for(ISpacecraft obj : objects)
System.out.println(obj.getCount() +" "+obj.getName());
}
Spacecraft
protected static int countCruiser;
ISpacecraft
int getCount();
cargoShip, ReserarchShip, etc..
private static int count
#Override
public int getCount() {
return this.count;
}
You could define a String member called typeName like this
protected String typeName;
public String getTypeName() {
return typeName;
}
into your abstract class and define the member in child class constructors like this
typeName = "Some Particular Type";
Now, you need a static Map for your abstract class:
public static Map<String, int> typeCounts;
and in your constructor of the abstract class do something like this:
if (typeCounts == null) {
typeCounts = new HashMap<String, int>();
}
if (typeCounts.get(getTypeName()) === null) {
typeCounts.put(getTypeName(), 1);
} else {
typeCounts.put(getTypeName(), typeCounts.get(getTypeName()) + 1);
}
Finally you will need to iterate typeCounts and use the keys and values for your output.
I'm trying to add let's say 5 classes that they all extend a General class and implements an init() method in a different way.
What I need is a way to store those classes while passing a number of chances for that Class to "happen"
For this I created a Class holder:
public class ClassHolder {
private Class<? extends GeneralOutcome> holdClass;
private int chances;
public ClassHolder(Class<? extends GeneralOutcome> holdClass, int chances) {
super();
this.holdClass = holdClass;
this.chances = chances;
}
public Class<? extends GeneralOutcome> getHoldClass() {
return holdClass;
}
public void setHoldClass(Class<? extends GeneralOutcome> holdClass) {
this.holdClass = holdClass;
}
public int getChances() {
return chances;
}
public void setChances(int chances) {
this.chances = chances;
}
}
Also a GeneralOutcome class that the ones that will be added to a list will extend:
public class GeneralOutcome {
public void init(String text, int times) {
}
}
And the way I'm adding them to a list:
public class Randomizer {
private static List<ClassHolder> myList = new ArrayList<ClassHolder>();
private static ClassHolder outcome01 = new ClassHolder(Outcome01.class, 10);
private static ClassHolder outcome02 = new ClassHolder(Outcome02.class, 10);
private static ClassHolder outcome03 = new ClassHolder(Outcome03.class, 10);
private static ClassHolder outcome04 = new ClassHolder(Outcome04.class, 10);
private static ClassHolder outcome05 = new ClassHolder(Outcome05.class, 10);
public static void main(String[] args) {
for(int i = 0; i < outcome01.getChances(); i++) {
myList.add(outcome01);
}
for(int i = 0; i < outcome02.getChances(); i++) {
myList.add(outcome02);
}
for(int i = 0; i < outcome03.getChances(); i++) {
myList.add(outcome03);
}
for(int i = 0; i < outcome04.getChances(); i++) {
myList.add(outcome04);
}
for(int i = 0; i < outcome05.getChances(); i++) {
myList.add(outcome05);
}
System.out.println(myList.size());
int rand = (int) (Math.random() * myList.size());
System.out.println(rand);
ClassHolder theHoldClass = myList.get(rand);
System.out.println(theHoldClass.getHoldClass());
Class<? extends GeneralOutcome> theOutcome = theHoldClass.getHoldClass();
theOutcome.init();
}
}
The problem is that I'm not able (Don't know how really) cast back to GeneralOutcome to I can access the .init() method.
I get The method init() is undefined for the type Class<capture#3-of ? extends GeneralOutcome>
I know this isn't the best way to do this. So I'm open to both, a fix for this and also what would be a better way to achieve something like this.
What you are trying to do here doesn't work for some reasons.
First of all, your init method isn't static. So that call
Class<? extends GeneralOutcome> theOutcome = theHoldClass.getHoldClass();
theOutcome.init();
leads directly to a compile-time error.
But then, the whole design looks strange. What is the point of holding Class objects in the first place?
Why don't you create an interface
public interface OutcomeFunctionality {
public void foo(String text, int times);
}
to later instantiate objects of whatever class implementing that interface? So that you can finally can deal with lists of such objects (together with those probabilities)?
[ I used the name foo on purpose: alone the strange name "init" makes it very unclear what your code is intended to do! In that sense you should rethink your design, and find better method names to express what those methods will be doing! ]
Long story short: using/holding Class objects doesn't buy you anything in your example code - it only adds complexity. So my advise is: start working there and get rid of that "detour". You might also want to read about the Open/Closed principle - that could give you some guidance how a good OO design looks like that uses abstract classes / subclassing in order to split "behavior" between base and derived classes.
Say I have 3 different classes (Class1, Class2, Class3), and each class has a method called ".update(String x)".
Now I want to read a line in a .csv file, I separate the values by comma and get a list with each string value indexed , for example "Foo, bar, barz" becomes {"foo", "bar", "barz").
Is it possible in Java to make a list of objects (Obj1, Obj2, Obj3), one for each class and for each value on my list of strings, call the .update of each object with the according index of my list of strings as the parameter?
for example:
package Test;
import java.util.ArrayList;
import java.util.List;
class Class1{
private String string;
public void update(String s){
this.string = s;
}
public String str(){
return this.string;
}
}
class Class2{
private String string;
public void update(String s){
this.string = s;
}
public String str(){
return this.string;
}
}
class Class3{
private String string;
public void update(String s){
this.string = s;
}
public String str(){
return this.string;
}
}
public class Testing {
public static void main(String[] args) {
List<Object> object = new ArrayList<Object>();
Class1 class1 = new Class1();
Class2 class2 = new Class2();
Class3 class3 = new Class3();
object.add(class1);
object.add(class2);
object.add(class3);
String string_list[] = {"foo" , "bar", "barz"};
for(int i = 0 ; i < object.size(); i++) {
object.get(i).update(string_list[i]);
}
}
}
hence obj1.update("foo"), obj2.update("bar"), obj3.update("barz")
I keep getting a "cannot resolve method" error in the loop.
Error:(68, 26) java: cannot find symbol
symbol: method update(java.lang.String)
location: class java.lang.Object)
But when I change the object reference in the loop to an object and not a reference it works fine. Logically it seems correct, but it seems like an ArrayList list isn't the right data structure to hold objects? or maybe it is and I'm doing it wrong, anyone have any suggestions why it's not working and how I can fix it?
Thanks.
you can do that, but for that you need your list of objects to be of a type that declares the update() method. If you want the objects to be of different classes, you need to have some interface or abstract class that all three implement/extend, and that interface/abstract class should declare update method.
should be something like this:
public interface MyInterface {
public void update(String str);
}
public class Object1 implements MyInterface {
#Override
public void update(String str) {
...
}
}
/// same for object 2 and 3
String[] string_list = {"foo", "bar", "barz"}
MyInterface[] obj_list = {Obj1, Obj2, Obj3}
...
...
Am new in java and try to get over it. I have data like (String URL, int Score) and i want to implement it in Array List. I've searched about how to implement multiple type of variable in ArrayList or LinkedList and found that the solution is to create sub class from super class and i create this sub class:
public class MySubClass extends MyList{
public String URL;
public int UrlScore;
public MySubClass (String a, int b){
URL = a;
UrlScore = b;
}
}
And my super class is:
import java.util.ArrayList;
public class MyList {
public static void main(String[] args) {
ArrayList <MySubClass> myList_1 = new ArrayList <MySubClass> ();
myList_1.add("http://www.something.com", 5);
System.out.println(myList_1);
}
}
I've got error when i try to use Add Add object ? The error said:
The method add(int, MySubClass) in the type ArrayList is not applicable for the arguments (String, int)
Can you tell me please where am doing the wrong ? And how can i fixed it ? Thanks in advance.
You can fix it via creating object of MySubClass and adding it to the list E.g.
MySubClass obj = new MySubClass("http://www.something.com", 5);
myList_1.add(obj);
You are supposed to add an instance of MySubClass to the list :
myList.add(new MySubClass("http://www.something.com", 5));
BTW, there is no need for MySubClass to be a sub-class of MyList.
As mentioned in the comments, you should override the toString() method in your MySubClass in order to display each instance of MySubClass as you wish.
A possible implementation :
public class MySubClass
{
public String URL;
public int UrlScore;
public MySubClass (String a, int b)
{
URL = a;
UrlScore = b;
}
public String toString()
{
return URL + "=" + UrlScore;
}
}
import java.util.ArrayList;
public class MyList {
public static void main(String[] args) {
ArrayList <MySubClass> myList_1 = new ArrayList <MySubClass> ();
MySubClass myobj = new MySubClass("http://www.something.com", 5);
myList_1.add(myobj);
}
}
Try something like that and the code will work.
This question already has answers here:
How to access Java array list data from another class
(2 answers)
Closed 8 years ago.
I want to store the input in my dictionary class so that I can search the words within this class. But I also need to use the array in other classes. Does anyone have an idea of how I can add input to my Dictionary() constructor?
Does anyone have an idea of how to fix this??
Thank you so much in advance!!!!
public class Dictionary {
// Private data fields
public ArrayList<String> dict;
Dictionary() {
dict = new ArrayList<String>();
}
public void add (String s){
dict.add(s);
}
public int size (){
return dict.size();
}
public String get(int i) {
return dict.get(i);
}
public ArrayList<String> getList(){
return dict;
}
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.print("Must have a file.");
System.exit(1);
}
try {
File dictionaryFile = new File(args[0]);
Scanner fin = new Scanner(dictionaryFile);
System.out.println(dictionaryFile.getAbsolutePath());
if (!dictionaryFile.exists()) {
System.out.println("Dictionary " + args[0] + "does not exist");
}
else if (!dictionaryFile.canRead()) {
System.out
.println("Dictionary " + args[0] + " cannot be read.");
}
Dictionary dict = new Dictionary();
while (fin.hasNext()) {
dict.add(fin.nextLine());
}
for (int i = 0; i < dict.size(); i++) {
System.out.println(dict.get(i));
}
} catch (FileNotFoundException e) {
System.out.println("No such file found " + args[0]);
}
}
}
/**
*This is the class I want to reference the array in
*/
public class FindWords {
public static void main(String[] args) {
Dictionary dictionary = new Dictionary();
System.out.print(dictionary.getList());
}
}
Okay...the problem is you are creating a new dictionary object in this class and your array list is associated with an Object or it is defined at the object level.
So, a new arraylist gets created everytime you instantiate a Dictionary object.
Try, making the arraylist as static in your Dictionary class.
for example,
public static ArrayList<String> yourArrayList;
Now, once you have added some elements in your Dictionary in the main method, you can access that array list from FindWord class like
Dictionary.dict
or, if you are not in a position to take that decision of making array list static in dictionary class then you need to initialize the list in FindWord class too as your FindWord class code shows that you are not adding elements in the dict list here.
Here, let me try again.
Why null?
public class: FindWords {
public static void main(String[] args) {
Dictionary dictionary = new Dictionary();//1
/***
. your list initialization code should come here
. It could be a code block or a method defined in Dictionary class itself
. which can be called like dictionary.initializeList();
***/
System.out.print(dictionary.getList()); //3
}
}
here, dictionary object has an arraylist associated with it(true) but it is not initialized yet. So, when you are saying
dictionary.getList();
it is actually fetching you the uninitialized list.
Modify your findwords class a s following
public class FindWords {
Dictionary dict=null;
public void (Dictionary dict){
this.dict = dict;
}
public void print(){
for(int i=0;i<dict.getList.size();i++)
{
System.out.println(dict.getList.get(i));
}
}
after that just before fininshing your try block add the following lines
FindWords f = new FindWords(dict);
f.print();