android/java concept to call all getter methods with a single loop - java

I am doing an assignment and stuck at this point:
I have a class in which i have 30 getter and setter method.
public class example{
public String get1(){
return someString1;
}
public String get2(){
return someString1;
}
public String get3(){
return someString4;
}
and so on...
public String get30(){
return someString30;
}
}
Now i want to call all getter method with a single loop like
for(int i= 1; i<=30;i++){
// String total = get1()+get2()+get3()...............
}
what should i do?
Edit: i did it using reflection :
http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
Thanks Ricky

The commented code is the only way to do that. But this is a symptom that your design is incorrect. Rather than having 30 properties of type String, you should certainly have one property of type String[] or List<String>.
Then you could do:
List<String> list = getListOfStrings();
StringBuilder builder = new StringBuilder();
for (String s : list) {
builder.append(s);
}
String concatenation = builder.toString();

If these are the standard accessors then better to go for List and do get(index)
else Reflection hack will help
public class Example{
private List<Integer> marks = new ArrayList<Integer>();
now loop
for(int i= 1; i<=30;i++){
total += marks.get(i);
}

Just override the toString() method in the example class like this:
#Override
public String toString() {
return someString1 + " " + someString2 + " " + someString3;
}

I did it using reflection :
http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

Related

Need assistance with question on java generics [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 2 years ago.
My output is currently:
Avengers#15db9742 Avengers#6d06d69c
I need to figure out how to display the names as well, using the generic print method. I've been trying things like: GenericMethod_violette.<Avengers>print(avenger.getName()) and GenericMethod_violette.<Avengers>print(avenger.trueIdentity()) but after days on this I seem to be stuck.
My output needs to be:
Avengers#15db9742 Avengers#6d06d69c
Tony Stark, Bruce Banner
My GenericMethod_violette.java:
import java.io.ObjectInputStream.GetField;
public class GenericMethod_violette {
public static void main(String[] args ) {
Avengers[] avenger = { new Avengers("Tony Stark"), new Avengers("Bruce Banner")};
GenericMethod_violette.<Integer>print(integers);
GenericMethod_violette.<String>print(strings);
GenericMethod_violette.<Avengers>print(avenger);
}
public static <E> void print(E[] list) {
for (int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
System.out.println();
}
}
My Avengers.java:
public class Avengers
{
private String trueIdentity;
public Avengers(String name)
{
trueIdentity = name;
}
public String getName()
{
return trueIdentity;
}
public String sayTrueIdentity()
{
return "Hello, I'm " + trueIdentity + "!";
}
}
you can use write toString inside Avengers
public class Avengers
{
private String trueIdentity;
public Avengers(String name)
{
trueIdentity = name;
}
public String getName()
{
return trueIdentity;
}
public String sayTrueIdentity()
{
return "Hello, I'm " + trueIdentity + "!";
}
// write any format you want to print
#override
public String toString()
{
return this.getName() + this.sayTrueIdentity();
}
}
then change your GenericMethod_violette.print method to use toString()
public static <E> void print(E[] list) {
for (int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
System.out.println();
}
Reason for Avengers print format - Avengers#15db9742
In java all objects have a toString() method, which is invoked when you try and print the object.
System.out.println(myObject); // invokes myObject.toString()
This method is defined in the Object class (the superclass of all Java objects). The Object.toString() method returns a fairly ugly looking string, composed of the name of the class, an # symbol and the hashcode of the object in hexadecimal. The code for this looks like:
// Code of Object.toString()
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
So you need #overrride toString method.
Your print result of Avengers#15db9742 would mean that it is an object that you printed. If you want to print something meaningful, you need to override the toString() method of said object. In this case, of your Avengers object.
public String toString(){
return trueIdentity;
}
Added notes from #markspace of java toString().
The class Avengers doesn't override the Object::toString method which System.out.println implicitely uses in its implementation. I suggest you to read more at: How to override toString() properly in Java?.
However, this solution requires all the possible objects passed into the method to override such method, which you cannot guarantee. I recommend you to pass a Function<E, String> that exctracts from the generic type the field(s) as String to be printed out:
public static <E> void print(E[] array, Function<E, String> extractor) {
for (E e: array) {
System.out.print(extractor.apply(e) + " ");
}
System.out.println();
}
The usage is fairly simple (the generic type can be omitted as long as it is inferred):
// both following lines are basically identical
GenericMethod_violette.print(avenger, a -> a.getName());
GenericMethod_violette.print(avenger, Avenger::getName);
// if Avengers have more of the fields or they are to be customized, ex.:
GenericMethod_violette.print(avenger, a -> "Mr." + a.getName().toUpperCase());
Disclaimer: This solution requires Java 8. If you use Java 7 or lower, you are stick to override the Object::toString in all the expected classes:
#Override
public String toString() {
return this.getName();
}

Java: pass in a string and store it

How would I create a method that has the input of a string and output of all the strings that were input into it like a super string?
for example in the main class:
a= "fido"
b= "rufus"
c= "dog"
superString(a);
superString(b);
superString(c);
System.out.println(superString()); should be "fidorufusdog"
so far I have=
public static String superString (String sb) {
StringBuilder ssb = new StringBuilder(32);
ssb = ssb.append(sb);
return ssb.toString();
}
My code below is what I am working on for a stock simulator:
public class Operators {
public static void operate(double price, double low, String company){
double percent = (price/low-1)*100;
double rpercent = Math.round(percent * 100.0) / 100.0;
StringBuilder sb = new StringBuilder(32);
if(rpercent <= 10) {
sb.append(company + " is trading at:");
sb.append("the current price is: " + price);
sb.append("the 52 week low is: " + low);
sb.append("percent of 52 week low is: " + rpercent);
}
}
}
The operate method is called in a for loop in my main method 506 times and I would like to take all 506 sb string and create a super string of all the results
I hope I do not underestimate the depth of the question or have your question wrong, but to me it sounds like you are asking for the static keyword?
class SomeClass {
static StringBuilder accumulator = new StringBuilder();
public String superString (String sb) {
SomeClass.accumulator.append(sb);
return ssb.toString();
}
}
This is simple usecase of the Java static keyword. Since accumulator is declared static there will be a single instance of the variable. And this single instance will be accessed by instances of the class SomeClass. For example:
SomeClass a;
SomeClass b;
a.superString("aaa");
b.superString("bbb");
// now accumulator.toString() returns "aaabbb"
Declare that string builder as the static member containing class and initialize it only once
static StringBuilder ssb;
public static String superString (String sb) {
if(ssb == null)
ssb = new StringBuilder(32);
ssb = ssb.append(sb);
return ssb.toString();
}
For this kind of probelm you've two choice :
Simple : create a static variable in the Java class, and manipulate it.
improve : create a design model which support your need.
Ex 1 :
public class Operators {
private static String text ="";
public static String superString(String sb) {
if (sb != null) {
text = text.concat(sb);
}
return text;
}
}
Ex 2 : you can use a Collecion or a List of strings.
This is poor OOP design. You would be much better off creating a class for Stock objects and overriding toString in the Stock class(or creating some other simple output method). Then add each instance of Stock to an array and call the each object's toString (or other output method you defined).

(Java) How to return objects from a list as a string or array of strings?

EDIT: I have uploaded both full class files and a tester file to dropbox in case you want to try it out yourselves: https://www.dropbox.com/sh/03qsecq3bd55w78/AAA_PT_BczNGl7cTZO_Zf_qUa?dl=0
First off, sorry if this is a very simple question - I've only just started working with java and I don't have a lot of programming experience at all.
So I have two classes: Posada and Camino. Posada contains a list of Camino objects. I need to override Posada's toString method so that it returns a string containing all of the toString methods of the Camino objects its list contains, like so:
Posada:
public class Posada {
/*other attributes*/
private List<Camino> listCaminos;
/*Getters*/
public List<Camino> getLisaCaminos() {
return listCaminos;
}
/*Builder*/
public Posada(String nombre, int engRecuperada) {
/*Other attributes*/
this.listaCaminos = new ArrayList<Camino>();
}
/*Methods*/
public String getStringToReturn(){
String[] arrayCaminos = listCaminos.toArray(new
String[listCaminos.size()]);
String string = "";
string += /*Some other attributes that go before the Camino objects
and work fine*/;
for(int i = 0; i < listCaminos.size(); i++) {
string += ", " + arrayCaminos[i];
}
return string;
}
/*toString*/
#Override
public String toString() {
return getStringToReturn(); //failure
}
}
Camino
public class Camino {
/*Attributes*/
private Posada origin;
private Posada destination;
private int cost;
private static int costTotal;
/*Contructor*/
public Camino(Posada origin, Posada destination, int cost){
this.origin = origin;
this.destination = destination;
this.cost = cost;
Camino.costTotal = Camino.costTotal + cost;
}
/*Getters*/
public int getCost() {
return cost;
}
public Posada getDestination() {
return destination;
}
public Posada getOrigin() {
return origin;
}
/*Methods. Irrelevant*/
/*toString*/
#Override
public String toString() {
return "(" + getOrigin() + "--" + getCost() + "-->" +
getDestination()+ ")";
}
}
So the expected result when printing Posada should be something like "Other_attributes, (originCamino1--costCamino1-->destinationCamino1), (originCamino2--costCamino2-->destinationCamino2), (..), (originCaminoN--costCaminoN-->destinationCaminoN)", N being the total number of Camino objects in the list. However, I keep getting the following error:
Exception in thread "main" java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at java.util.ArrayList.toArray(Unknown Source)
at apartado1.Posada.getStringToReturn(Posada.java:106)
at apartado1.Posada.toString(Posada.java:121)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
I know it's got to be something really easy to fix, but I've been looking around and it just won't work no matter what I do. I've tried using toString() and toArray(), but I get the same results. Here's hoping you can help me. Thanks in advance!
Why does the default implementation of ArrayList not work ? This this:
#Override
public String toString() {
return listCaminos.toString();
}
listCaminos.toArray() must return an array of Camino. You can't pass in String[].
Change the first line of Camino.getStringToReturn() to
Camino[] arrayCaminos = listCaminos.toArray(new Camino[listCaminos.size()]);
Should work fine now.
EDIT: Looking at your code again, I don't understand why you're using an array in the first place. Why not iterate over the list elements?
A simpler way to do this with Java 8:
#Override
public String toString() {
return "Other_attributes, " +
listCaminos.stream()
.map(Camino::toString)
.collect(Collectors.joining(", "));
}
There is no need to convert the list to an array before iterating it, and with Java 8 streams there is no need to even iterate the list to create a comma-delimited string of the Camino objects.
You could use either what Matthias suggested, or if you want a customized output, you could loop through each of the elements and concatenate their toString outputs.
Something like this:
public String toString(){
StringBuilder builder = new StringBuilder();
for (Camino camino : listCaminos) {
builder.append(camino.toString()).append(",");
}
return builder.toString();
}
You can strip off the extra "," at the end.
I'd rather use a foreach loop inside toString, like:
public String toString()
{
String ret = "";
for (Camino camino : listCaminos)
{
ret += camino.toString() + "\n";
}
return ret;
}
Instead of using \n (as new line), you can use comma as your example.
Evenmore, it could be improved using StringBuilder if performance improvements are necessary.

how to make more than condition in toString method

I want to list all names that end with "Reda" and ignore case sensitivity, I have tried the condition in the toString method at the bottom, but it would not print any thing.
public class Customer {
public static void main(String[] args) throws IOException {
File a = new File("customer.txt");
FileWriter v = new FileWriter(a);
BufferedWriter b = new BufferedWriter(v);
PrintWriter p = new PrintWriter(b);
human Iman = new human("Iman", 5000);
human Nour = new human("Nour", 3500);
human Redah = new human("Redah", 0);
human iman = new human("iman", 200);
human MohamedREDA = new human("MohamedREDA", 3000);
human Mohamed_Redah = new human("Mohamed Redah", 2000);
human[] h = new human[6];
h[0] = Iman;
h[1] = Nour;
h[2] = Redah;
h[3] = iman;
h[4] = MohamedREDA;
h[5] = Mohamed_Redah;
p.println(Iman);
p.println(Nour);
p.println(Redah);
p.println(iman);
p.println(MohamedREDA);
p.println(Mohamed_Redah);
p.flush();
}
}
class human {
public String name;
public double balance;
public human(String n, double b) {
this.balance = b;
this.name = n;
}
#Override
public String toString() {
if (name.equalsIgnoreCase("Reda") && (name.equalsIgnoreCase("Reda"))) {
return name + " " + balance;
} else
return " ";
}
}
Please avoid putting condition in toString method. Remove the condition there
public String toString() {
return name + " " + balance;
}
and change your logic in Customer class
human[] h = new human[6];
h[0] = Iman;
h[1] = Nour;
h[2] = Redah;
h[3] = iman;
h[4] = MohamedREDA;
h[5] = Mohamed_Redah;
for (int i = 0; i < h.length; i++) {
if (h[i].name.toLowerCase().endsWith("reda")) { // condition here
p.println(h[i]);
}
}
And make use of loops do not duplicate the lines of code.Every where you are manually writing the lines.
Check Java String class and use required methods to add condition.
String redahname = ("Redah").toLowerCase(); //put your h[0] instead of ("Redah")
if(name.endsWith("redah")){ //IMPORTANT TO BE IN LOWER CASE, (it is case insenitive this way)
//your code here if it ends with redag
System.out.println(redahname);
} //if it does not end with "redah" it wont out print it!
You can use this, but can you please explain your question more? What exactly do you need?
try this
#Override
public String toString() {
if (name.toLowerCase().endsWith("reda"))) {
return name + " " + balance;
} else
return " ";
}
String.equals() is not what you want as you're looking for strings which ends with "Reda" instead of those equal to "Reda". Using String.match or String.endsWith together with String.toLowerCase will do this for you. The following is the example of String.match:
public class Reda {
public static void main(String[] args) {
String[] names = {"Iman", "MohamedREDA", "Mohamed Redah", "reda"};
for (String name : names) {
// the input to matches is a regular expression.
// . stands for any character, * stands for may repeating any times
// [Rr] stands for either R or r.
if (name.matches(".*[Rr][Ee][Dd][Aa]")) {
System.out.println(name);
}
}
}
}
and its output:
MohamedREDA
reda
and here is the solution using endsWith and toLowerCase:
public class Reda {
public static void main(String[] args) {
String[] names = {"Iman", "MohamedREDA", "Mohamed Redah", "reda"};
for (String name : names) {
if (name.toLowerCase().endsWith("reda")) {
System.out.println(name);
}
}
}
}
and its output:
MohamedREDA
reda
You shouldn't put such condition in toString() method cause, it's not properly put business application logic in this method.
toString() is the string representation of an object.
What you can do, is putting the condition before calling the toString() , or making a helper method for this.
private boolean endsWithIgnoringCase(String other){
return this.name.toLowerCase().endsWith(other.toLowerCase());
}
None of your humans are called, ignoring case, Reda, so your observation of no names printed is the manifestation of properly working logic.
Your condition is redundant: you perform the same test twice:
name.equalsIgnoreCase("Reda") && (name.equalsIgnoreCase("Reda"))
If you need to match only the string ending, you should employ a regular expression:
name.matches("(?i).*reda")
toString is a general-purpose method defined for all objects. Using it the way you do, baking in the business logic for just one special use case, cannot be correct. You must rewrite the code so that toString uniformly returns a string representation of the object.

Invoking a same method just once in java

I have four different classes classA, classB, classC and classD. All the four classes have the same static method search() which takes two string parameters. If i want to invoke static method search in four different classes from main class at once. How can I do that. For now my code is as follows for main class. I need to execute the same thing for other 3 classes also. How can i do that and display the results of other 3 in the same way as for classA. The way search is done in 4 classes r different but they should give the same result.
Main() {
Object[] zy;
for (String pattern : Read.arrayList) {
List<Integer> results = ClassA.findAll(pattern, dataToSearch);
zy = results.toArray();
for (int i = 0; i < zy.length; i++) {
System.out.println(" Pattern searched " + pattern + " match is found at index : "+ results);
}
}
if (zy.length == 0) {
System.out.println("Nothing matched");
}
}
I strongly recommend you change this to non-static methods. Look how easy and nice is when you will seperate an interface:
public interface Common {
List<Integer> findAll(String pattern, String dataToSearch);
}
public class A implements Common ...
public class B implements Common ...
public class C implements Common ...
public class D implements Common ...
// in main:
List<Common> allYourClasses = new ArrayList<Common>();
allYourClasses.add(new A());
allYourClasses.add(new B());
allYourClasses.add(new C());
allYourClasses.add(new D());
List<Integer> result = new ArrayList<Integer>();
for (Common c : allYourClasses) {
result.addAll(c.findAll(pattern, dataToSearch));
}
1 - You should NOT do this. Avoid static methods. One of the reason being they can not be called without the exact class. A group of classes that implement a simple interfaces will work faster, safer and better in every way
2 - You can (but you shouldn't) do something like this:
for (Class<?> clazz : new Class[] { ClassA.class, ClassB.class,
ClassC.class }) {
Object[] zy = null;
String dataToSearch = "";
String[] arrayList = { "a" };
for (String pattern : arrayList) {
List<Integer> results = findAllForClass(clazz, pattern,
dataToSearch);
zy = results.toArray();
for (int i = 0; i < zy.length; i++) {
System.out.println(" Pattern searched " + pattern
+ " match is found at index : " + results);
}
}
if (zy.length == 0) {
System.out.println("Nothing matched");
}
}
#SuppressWarnings("unchecked")
public static List<Integer> findAllForClass(Class<?> clazz, String pattern,
String dataToSearch) {
List<Integer> list = null;
try {
list = (List<Integer>) clazz.getDeclaredMethod("findAll", String.class,
String.class).invoke(null, pattern, dataToSearch);
} catch (Exception e) {
list = Collections.emptyList();
}
return list;
}
You see the #supresswarning and the try/catch? well, this is a hint: is telling you you this code is at least suspicious. It is in fact unsafe, non well performant, and is a stupid workaround.
(But we all did something like that once in our lives)
I can't really figure out why would anyone do that.
That said, you could have a method taking a Class as a parameter and calling the method explicitly by name (getMethod.../invoke()).
That puts you back in non static world and you can iterate over the classes you want to invoke. (But again, why use statics in the first place?)
Pseudo untested code:
public void invokeStatic(Class clazz, String method, Class<?> paramsTypes[], Object[] params) {
Method method = clazz.getMethod(method, paramsType);
method.invoke(params);
}
If you want to group all of the results together, just keep adding results to your list:
List<Integer> results = ClassA.findAll(pattern, dataToSearch);
results.addAll(ClassB.findAll(pattern, dataToSearch));
// etc.

Categories