How to fill randomly chosen object of class with random generated parameters? - java

I have to change my code to solution from using reflection to generation random parameters.
I couldn't figure out how to made this implementation...
Here is class generator:
public class SweetsGenerator implements Generator<Sweets>, Iterable<Sweets> {
private static final Logger LOG = Logger.getLogger(SweetsGenerator.class);
#SuppressWarnings("rawtypes")
private Class[] types = {
WhiteChocolate.class, MilkChokolate.class, DarkChocolate.class,
DesertChocolate.class, PorousChocolate.class,
};
private static Random rand = new Random();
public SweetsGenerator() {
}
private int size = 0;
public SweetsGenerator(int sz) {
size = sz;
}
public Sweets next() {
try {
return (Sweets) types[rand.nextInt(types.length)].newInstance();
} catch (Exception e) {
LOG.error("RuntimeException", e);
throw new RuntimeException(e);
}
}
class SweetsIterator implements Iterator<Sweets> {
int count = size;
public boolean hasNext() {
return count > 0;
}
public Sweets next() {
count--;
return SweetsGenerator.this.next();
}
public void remove() { // Not implemented
LOG.error("UnsupportedOperationException");
throw new UnsupportedOperationException();
}
};
public Iterator<Sweets> iterator() {
return new SweetsIterator();
}
}
How to circumvent this approach and create new class element, for example as:
new WhiteChocolate((rand.nextDouble() * 100) + 1, (rand.nextDouble() * 200) + 1);
I can't it combine with randomise generation class witch element we can create.
Here is content of Sweets abstract class and one of it implementation:
public abstract class Sweets {
private double sugarLevel;
private double weight;
public double getSugarLevel() {
return sugarLevel;
}
public double getWeight() {
return weight;
}
public void setSugarLevel(double sugarLevel) {
this.sugarLevel = sugarLevel;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName() + " " + sugarLevel + " " + weight);
return sb.toString();
}
}
public class Chocolate extends Sweets {
public Chocolate() {
}
public Chocolate(double aSugarLevel, double aWeight) {
setSugarLevel(aSugarLevel);
setWeight(aWeight);
}
}
UPDATE:
I tried to modify next() by skiwi suggestion.
Changed version is next:
public Sweets next() {
Sweets current = instances[rand.nextInt(instances.length)];
Double param1 = (rand.nextDouble() * 100) + 1;
Double param2 = (rand.nextDouble() * 200) + 1;
System.out.println("parameters: " + Math.round(param1) + " " + Math.round(param2));
try {
return (Sweets) current.getClass()
.getConstructor(Double.class, Double.class)
.newInstance(Math.round(param1), Math.round(param2));
// Report programmer errors at run time:
} catch (Exception e) {
LOG.error("RuntimeException", e);
throw new RuntimeException(e);
}
}
But it throws next bunch of exceptions:
23:25:51,337 ERROR main SweetsGenerator:next:52 - RuntimeException
java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
at java.lang.Class.getConstructor0(Class.java:2800)
at java.lang.Class.getConstructor(Class.java:1708)
at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:48)
at com.epam.lab.NewYearGift.generate(NewYearGift.java:37)
at com.epam.lab.GiftList.generateGift(GiftList.java:47)
at com.epam.lab.GiftList.main(GiftList.java:59)
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:53)
at com.epam.lab.NewYearGift.generate(NewYearGift.java:37)
at com.epam.lab.GiftList.generateGift(GiftList.java:47)
at com.epam.lab.GiftList.main(GiftList.java:59)
Caused by: java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
at java.lang.Class.getConstructor0(Class.java:2800)
at java.lang.Class.getConstructor(Class.java:1708)
at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:48)
... 3 more
Solution for this problem was to change one line:
return (Sweets) current.getClass().getConstructor(double.class, double.class)
.newInstance(Math.round(param1), Math.round(param2));
How to safe this logic of generator and create randomly elements with parameters?
Any suggestions?

If you have a constructor contract like public WhiteChololate(Double a, Double b), you can call the following to create a new instance:
Double a = 1d;
Double b = 2d;
WhiteChocolate.class.getConstructor(Double.class, Double.class).newInstance(a, b);
This will construct the required instance, not ethat I am using this syntax over Class<?>.newInstance(), since as described here:
Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException.
So using Constructor.newInstance(...) is both more safe and is the only one that will satisfy your needs.
Note that you need to specify the parameters type in the .getConstructor() call and not the value yet.

Related

Errors about compareTo & TreeSet (Java)

So I've been trying to figure out how Collections work in Java (by looking at an old project we did in uni) but I keep getting some errors I cannot fix, it has something to do with the Comparable function
This is my first class:
import java.io.*;
import java.util.*;
public class Client {
private int hour;
private int minute;
private int min_per_stay;
private double price;
public Client(int h, int m, int mps, double p)
{
this.hour = h;
this.minute = m;
this.min_per_stay = mps;
this.price = p;
}
public void SetHour(int h)
{
this.hour = h;
}
public void SetMin(int m)
{
this.minute = m;
}
public void SetMinPStay(int mps)
{
this.min_per_stay = mps;
}
public void SetPrice(double p)
{
this.price = p;
}
public int GetHour()
{
return hour;
}
public int GetMin()
{
return minute;
}
public int GetMinPStay()
{
return min_per_stay;
}
public double GetPrice()
{
return price;
}
public String toString()
{
return "Hours: " + this.hour +
" Minutes: " + this.minute +
" Minutes per stay:" + this.min_per_stay +
" Price: " + this.price + "\n";
}
public boolean equals(Client c) {
return (this.hour == ((Client)c).GetHour() && this.minute == ((Client)c).GetMin());
}
public int CompareTo(Client c)
{
if (this.hour<((Client)c).hour) return -1;
if(this.minute<((Client)c).minute) return -1;
if (this.hour>((Client)c).hour) return 1;
if(this.minute>((Client)c).minute) return 1;
return 0;
}
}
And my collection:
import java.io.*;
import java.util.*;
public class ClientCollection{
private SortedSet<Client> oClient = new TreeSet<Client>();
public ClientCollection()
{
}
public ClientCollection(String FileName)
{
try
{
Scanner sc = new Scanner(new File(FileName));
while(sc.hasNextLine())
{
oClient.add(new Client(sc.nextInt(),sc.nextInt(),
sc.nextInt(),sc.nextDouble()));
}
sc.close();
}
catch (FileNotFoundException e)
{
System.out.println("File not found!");
}
}
public void addClient(Client c)
{
oClient.add(c);
}
public List<Client> reverseList()
{
List<Client> oList1 = new ArrayList<Client>(oClient);
List<Client> oList2 = new ArrayList<Client>();
for(ListIterator<Client> it = (oList1.listIterator(oClient.size())); it.hasPrevious(); )
{
Client res = it.previous();
oList2.add(res);
}
return oList2;
}
public void printColl()
{
System.out.println(oClient.toString());
}
public static void main(String[] args)
{
ClientCollection oc = new ClientCollection("test.txt");
oc.printColl();
oc.reverseList();
oc.printColl();
}
}
and the errors I get are:
Exception in thread "main" java.lang.ClassCastException: Client cannot be cast to java.base/java.lang.Comparable
at java.base/java.util.TreeMap.compare(Unknown Source)
at java.base/java.util.TreeMap.put(Unknown Source)
at java.base/java.util.TreeSet.add(Unknown Source)
at ClientCollection.<init>(ClientCollection.java:20)
at ClientCollection.main(ClientCollection.java:56)
i'll be really happy if someone explains the errors to me, im still kinda new at this :(
Your Client class doesn't implement the Comparable<Client> interface (i.e. Client doesn't have a natural ordering).
Therefore, in order for it to be used as an element of a TreeSet, you must pass to the TreeSet<Client> constructor a Comparator<Client>, which specifies the ordering of Client elements.
Failing to do so results in ClassCastException, since the TreeSet class (or rather the TreeMap class that is uses behind the scenes) assumes that if you didn't supply a Comparator in the constructor, this means that your Client implements Comparable.
EDIT: Since you have a CompareTo method in the Client class, it looks like you intended to implement Comparable.
Change:
public class Client
to:
public class Client implements Comparable<Client>
and change:
public int CompareTo(Client c)
to:
public int compareTo(Client c)
You might want to modify the logic of your compareTo method, though.
Apart from what #Eran wrote, you need to write method names starting with a lower case letter. You can see that StackOverflow's formatter gets confused by it. It will also confuse anybody having to maintain your code.
Your compareTo method should look like this:
public int compareTo(final Client c)
{
final int diffHours = this.hour - c.hour;
if (diffHours == 0) {
return this.minute - c.minute;
} else {
return diffHours;
}
}
The casts are unnecessary, since the c parameter is already of type Client.

java.lang.Field equivalent in c++

I have a code that uses Field built in function in java and i could not find a way to replace it in c++ the code is shown below,
import java.lang.reflect.Field;
public class ParameterValue {
public String objectPath;
public Object objectReference;
public String fieldPath;
public String fieldPathNoCase;
public Field field;
public double value;
public ParameterValue(String path, ObjectTree tree, Field fieldInfo) {
objectPath = path;
objectReference = tree.getObject(path);
field = fieldInfo;
fieldPath = objectPath + "." + field.getName();
fieldPathNoCase = fieldPath.toLowerCase();
read();
}
public int getPrecision() {
if (field.getType().getName() == "float" || field.getType().getName() == "double")
return 2;
else
return 0;
}
public double getPrecisionMultiplier() {
return Math.pow(10, getPrecision());
}
public void read() {
String type = field.getType().getName();
try {
if (type.equals("double"))
value = field.getDouble(objectReference);
else if (type.equals("float"))
value = field.getFloat(objectReference);
else if (type.equals("int"))
value = field.getInt(objectReference);
else if (type.equals("byte"))
value = field.getByte(objectReference);
else
throw new RuntimeException();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
value = Math.round(value * getPrecisionMultiplier()) / getPrecisionMultiplier();
}
public void write() {
String type = field.getType().getName();
try {
if (type.equals("double"))
field.setDouble(objectReference, value);
else if (type.equals("float"))
field.setFloat(objectReference, (float)value);
else if (type.equals("int"))
field.setInt(objectReference, (int)Math.round(value));
else if (type.equals("byte"))
field.setByte(objectReference, (byte)Math.round(value));
else
throw new RuntimeException();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void rebind(ObjectTree tree) {
objectReference = tree.getObject(objectPath);
}
}
What i have understood from the code is that i need to find a class that can convert the value in it to Double, Float,etc. I have looked for something that can do this but i was not able to do so.
reference of the code:
https://www.programcreek.com/java-api-examples/index.php?source_dir=SecugenPlugin-master/src/sourceafis/simple/Fingerprint.java#
As per my knowledge there is no equivalent class in C++. Now for your requirement first you list out what are all a java.lang.reflect.Field class provides in java. Once you listed all the utility methods, just sort list all methods that you really requires in your C++ application. Once done you do create a C++ class with the same name and methods types and implement the logic by yourself if possible.

Calling the same method multiple times without overwriting previous values

Apologies if this is trivial to most but I just can't figure this issue out!!
I am creating a mock game where I have a start, end, and hops along. There are portals where if you go on a white portal you jump further ahead and there are black ones where you go backwards. I have set up the class as a POJO;
private int totalSize;
private int minDice;
private int maxDice;
private int whitePortalStart;
private int whitePortalEnd;
private int blackPortalStart;
private int blackPortalEnd;
private int startPosition = 1;
private int currentPosition;
public GameObject(){}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) throws Exception {
if(totalSize <= 0){
throw new Exception("Can't have a total distance of less than or equal to 0");
} else {
this.totalSize = totalSize;
}
}
public int getMinDice() {
return minDice;
}
public void setMinDice(int minDice) throws Exception {
if(minDice <= 0){
throw new Exception("Can't have a min dice value of less than or equal to 0");
} else {
this.minDice = minDice;
}
}
public int getMaxDice() {
return maxDice;
}
public void setMaxDice(int maxDice) throws Exception {
if(getMinDice() > maxDice){
throw new Exception("Cant have minimum dice number greater than the larger dice number");
} else {
this.maxDice = maxDice;
}
}
public int getWhitePortalStart() {
return whitePortalStart;
}
public void setWhitePortalStart(int whitePortalStart) throws Exception {
this.whitePortalStart = whitePortalStart;
}
public int getWhitePortalEnd() {
return whitePortalEnd;
}
public void setWhitePortalEnd(int whitePortalEnd) throws Exception {
this.whitePortalEnd = whitePortalEnd;
}
public int getBlackPortalStart() {
return blackPortalStart;
}
public void setBlackPortalStart(int blackPortalStart) throws Exception {
this.blackPortalStart = blackPortalStart;
}
public int getBlackPortalEnd() {
return blackPortalEnd;
}
public void setBlackPortalEnd(int blackPortalEnd) throws Exception {
this.blackPortalEnd = blackPortalEnd;
}
public GameObject builder(int n) throws Exception {
setTotalSize(n);
return this;
}
public GameObject whitePortal(int m, int o) throws Exception {
setWhitePortalStart(m);
setWhitePortalEnd(o);
return this;
}
public GameObject blackPortal(int o, int m) throws Exception {
setBlackPortalStart(o);
setBlackPortalEnd(m);
return this;
}
public GameObject dice(int i, int j) throws Exception {
setMinDice(i);
setMaxDice(j);
return this;
}
public int rollDice(){
Random random = new Random();
int min = getMinDice();
int max = getMaxDice();
return random.nextInt(max - min + 1) + min;
}
public void build(){
int totalDistance = getTotalSize();
currentPosition = startPosition;
while(currentPosition < totalDistance){
int diceValue = rollDice();
if(currentPosition + diceValue > getTotalSize()){
System.out.println("CurrentPosition : " + (currentPosition + diceValue) + ", is larger than the total size of the road - " + totalSize);
continue;
} else if(currentPosition + diceValue == getWhitePortalStart()){
System.out.println("You landed on a white portal. Advancing from position " + (currentPosition + diceValue) + " to " + getWhitePortalEnd());
currentPosition = getWhitePortalEnd();
} else if(currentPosition + diceValue == getBlackPortalStart()){
System.out.println("You landed on a black portal. Moving from position " + (currentPosition + diceValue) + " to " + getBlackPortalEnd());
currentPosition = getBlackPortalEnd();
} else {
System.out.println("You landed on " + (currentPosition + diceValue));
currentPosition += diceValue;
}
}
}
So in my main method I call the it like create and call this class like;
WorldOfOz oz = new WorldOfOz();
oz.go.builder(30)
.dice(1, 4)
.whitePortal(5, 12)
.blackPortal(13, 2)
.build();
My issue is when I want to add in more than 1 whitePortal/blackPortal
WorldOfOz oz = new WorldOfOz();
oz.go.builder(30)
.dice(1, 4)
.whitePortal(5, 12)
.whitePortal(18, 26)
.blackPortal(13, 2)
.build();
The values 18 - 26 override 5 - 12. How can I set this up so I can have multiple white and black portals?
It seems that your data structure is not enough to solve this problem.
You need to define a collection of whitePortals and a collection of blackPortals. If you do so calling the method whitePortal(5, 12) add a new white portal insted of setting the white portal values of the only white existing portal.
You need to define a class Portal
public class Portal {
private int portalStart;
private int portalEnd;
...
public Portal(int s, int e) {
this.portalStart = s;
this.portalEnd = e;
}
}
Then you can use it in the GameObject as follow:
public GameObject {
List<Portal> whitePortals;
List<Portal> blackPortals;
public GameObject() {
whitePortals = new ArrayList<Portal>();
blackPortals = new ArrayList<Portal>();
}
public GameObject addWhitePortal(int m, int o) throws Exception {
whitePortals.add(new Portal(m, o));
return this;
}
...
// You need to change other methods to follow a different data structure
}
Well, you can use the following approach:
Introduce a new "Portal" type with start/end attributes
Replace white/black portal attributes in your class with lists for white and black portals (or any other type of collection you like)
Replace getWhite/Black methods with access to lists
Refactor whitePortal and blackPortal method to create new instances of a portal object and add them to an appropriate collection
You can, of course, use arrays instead of collections, but that's a bit more cumbersome.
Also, assuming portals are collections, you probably need to add helper methods for operating on those. Depending on what your actual needs are.
public class Portal
{
private int start;
private int end;
public Portal(int start, int end) { ... }
public getStart() {...}
public getEnd() {...}
public setStart(int end) {...}
public setEnd(int start) {...}
}
public class GameObject
{
...
private List<Portal> whitePortals = new ArrayList<Portal>();
private List<Portal> blackPortals = new ArrayList<Portal>();
...
public GameObject whitePortal(int m, int o) throws Exception {
whitePortals.add(new Portal(m, o));
return this;
}
public GameObject blackPortal(int o, int m) throws Exception {
blackPortals.add(new Portal(m, o));
return this;
}
...
}

How to write a method that returns an instance of an abstract class?

I am a beginner in Java and i trying to understand the abstract classes.
Below is the code that I've written; the question is: how do i write a method that will return an instance of that class.
public abstract class VehicleEngine
{
protected String name;
protected double fabricationCons;
protected double consum;
protected int mileage;
public VehicleEngine(String n, double fC)
{
name = n;
fabricationCons = fC;
mileage = 0;
consum = 0;
}
private void setFabricationCons(double fC)
{
fabricationCons = fC;
}
public abstract double currentConsum();
public String toString()
{
return name + " : " + fabricationCons + " : " + currentConsum();
}
public void addMileage(int km)
{
mileage += km;
}
public double getFabricationConsum()
{
return fabricationCons;
}
public String getName()
{
return name;
}
public int getMileage()
{
return mileage;
}
//public VehicleEngine get(String name){
//if(getName().equals(name)){
//return VehicleEngine;
//}
//return null;
//}
}
public class BenzinVehicle extends VehicleEngine
{
public BenzinVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
if (getMileage() >= 75000) {
consum = getFabricationConsum() + 0.4;
} else {
consum = getFabricationConsum();
}
return consum;
}
}
public class DieselVehicle extends VehicleEngine
{
public DieselVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
int cons = 0;
if (getMileage() < 5000) {
consum = getFabricationConsum();
} else {
consum = getFabricationConsum() + (getFabricationConsum() * (0.01 * (getMileage() / 5000)));
}
return consum;
}
}
This is the main.
public class Subject2
{
public static void main(String[] args)
{
VehicleEngine c1 = new BenzinVehicle("Ford Focus 1.9", 5.0);
DieselVehicle c2 = new DieselVehicle("Toyota Yaris 1.4D", 4.0);
BenzinVehicle c3 = new BenzinVehicle("Citroen C3 1.6",5.2);
c1.addMileage(30000);
c1.addMileage(55700);
c2.addMileage(49500);
c3.addMileage(35400);
System.out.println(c1);
System.out.println(c2);
System.out.println(VehicleEngine.get("Citroen C3 1.6")); //this is the line with problems
System.out.println(VehicleEngine.get("Ford Focus "));
}
}
And the output should be:
Ford Focus 1.9 : 5.0 : 5.4
Toyota Yaris 1.4D : 4.0 : 4.36
Citroen C3 1.6 : 5.2 : 5.2
null
You can not return an instance of an abstract class, by definition. What you can do, is return an instance of one of the concrete (non-abstract) subclasses that extend it. For example, inside the VehicleEngine you can create a factory that returns instances given the type of the instance and the expected parameters, but those instances will necessarily have to be concrete subclasses of VehicleEngine
Have a look at the Factory Method pattern. Your concrete classes will implement an abstract method that returns a class instance.
Abstract classes do not keep a list of their instances. Actually no Java class does that. If you really want to do that, you could add a static map to VehicleEngine like this:
private static Map<String, VehicleEngine> instanceMap = new HashMap<String, VehicleEngine>();
and change your get method to a static one like this:
public static VehicleEngine get(String name) {
return instanceMap.get(name);
}
and add this line to the end of the constructor of VehicleEngine:
VehicleEngine.instanceMap.put(n, this);
this way every new instance created puts itself into the static map. However this actually is not a good way to implement such a functionality. You could try to use a factory to create instances, or you could consider converting this class into an enum if you will have a limited predefined number of instances.

How to return 2 values from a Java method?

I am trying to return 2 values from a Java method but I get these errors. Here is my code:
// Method code
public static int something(){
int number1 = 1;
int number2 = 2;
return number1, number2;
}
// Main method code
public static void main(String[] args) {
something();
System.out.println(number1 + number2);
}
Error:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - missing return statement
at assignment.Main.something(Main.java:86)
at assignment.Main.main(Main.java:53)
Java Result: 1
Instead of returning an array that contains the two values or using a generic Pair class, consider creating a class that represents the result that you want to return, and return an instance of that class. Give the class a meaningful name. The benefits of this approach over using an array are type safety and it will make your program much easier to understand.
Note: A generic Pair class, as proposed in some of the other answers here, also gives you type safety, but doesn't convey what the result represents.
Example (which doesn't use really meaningful names):
final class MyResult {
private final int first;
private final int second;
public MyResult(int first, int second) {
this.first = first;
this.second = second;
}
public int getFirst() {
return first;
}
public int getSecond() {
return second;
}
}
// ...
public static MyResult something() {
int number1 = 1;
int number2 = 2;
return new MyResult(number1, number2);
}
public static void main(String[] args) {
MyResult result = something();
System.out.println(result.getFirst() + result.getSecond());
}
Java does not support multi-value returns. Return an array of values.
// Function code
public static int[] something(){
int number1 = 1;
int number2 = 2;
return new int[] {number1, number2};
}
// Main class code
public static void main(String[] args) {
int result[] = something();
System.out.println(result[0] + result[1]);
}
You could implement a generic Pair if you are sure that you just need to return two values:
public class Pair<U, V> {
/**
* The first element of this <code>Pair</code>
*/
private U first;
/**
* The second element of this <code>Pair</code>
*/
private V second;
/**
* Constructs a new <code>Pair</code> with the given values.
*
* #param first the first element
* #param second the second element
*/
public Pair(U first, V second) {
this.first = first;
this.second = second;
}
//getter for first and second
and then have the method return that Pair:
public Pair<Object, Object> getSomePair();
You can only return one value in Java, so the neatest way is like this:
return new Pair<Integer>(number1, number2);
Here's an updated version of your code:
public class Scratch
{
// Function code
public static Pair<Integer> something() {
int number1 = 1;
int number2 = 2;
return new Pair<Integer>(number1, number2);
}
// Main class code
public static void main(String[] args) {
Pair<Integer> pair = something();
System.out.println(pair.first() + pair.second());
}
}
class Pair<T> {
private final T m_first;
private final T m_second;
public Pair(T first, T second) {
m_first = first;
m_second = second;
}
public T first() {
return m_first;
}
public T second() {
return m_second;
}
}
Here is the really simple and short solution with SimpleEntry:
AbstractMap.Entry<String, Float> myTwoCents=new AbstractMap.SimpleEntry<>("maximum possible performance reached" , 99.9f);
String question=myTwoCents.getKey();
Float answer=myTwoCents.getValue();
Only uses Java built in functions and it comes with the type safty benefit.
Use a Pair/Tuple type object , you don't even need to create one if u depend on Apache commons-lang. Just use the Pair class.
you have to use collections to return more then one return values
in your case you write your code as
public static List something(){
List<Integer> list = new ArrayList<Integer>();
int number1 = 1;
int number2 = 2;
list.add(number1);
list.add(number2);
return list;
}
// Main class code
public static void main(String[] args) {
something();
List<Integer> numList = something();
}
public class Mulretun
{
public String name;;
public String location;
public String[] getExample()
{
String ar[] = new String[2];
ar[0]="siva";
ar[1]="dallas";
return ar; //returning two values at once
}
public static void main(String[] args)
{
Mulretun m=new Mulretun();
String ar[] =m.getExample();
int i;
for(i=0;i<ar.length;i++)
System.out.println("return values are: " + ar[i]);
}
}
o/p:
return values are: siva
return values are: dallas
I'm curious as to why nobody has come up with the more elegant callback solution. So instead of using a return type you use a handler passed into the method as an argument. The example below has the two contrasting approaches. I know which of the two is more elegant to me. :-)
public class DiceExample {
public interface Pair<T1, T2> {
T1 getLeft();
T2 getRight();
}
private Pair<Integer, Integer> rollDiceWithReturnType() {
double dice1 = (Math.random() * 6);
double dice2 = (Math.random() * 6);
return new Pair<Integer, Integer>() {
#Override
public Integer getLeft() {
return (int) Math.ceil(dice1);
}
#Override
public Integer getRight() {
return (int) Math.ceil(dice2);
}
};
}
#FunctionalInterface
public interface ResultHandler {
void handleDice(int ceil, int ceil2);
}
private void rollDiceWithResultHandler(ResultHandler resultHandler) {
double dice1 = (Math.random() * 6);
double dice2 = (Math.random() * 6);
resultHandler.handleDice((int) Math.ceil(dice1), (int) Math.ceil(dice2));
}
public static void main(String[] args) {
DiceExample object = new DiceExample();
Pair<Integer, Integer> result = object.rollDiceWithReturnType();
System.out.println("Dice 1: " + result.getLeft());
System.out.println("Dice 2: " + result.getRight());
object.rollDiceWithResultHandler((dice1, dice2) -> {
System.out.println("Dice 1: " + dice1);
System.out.println("Dice 2: " + dice2);
});
}
}
You don't need to create your own class to return two different values. Just use a HashMap like this:
private HashMap<Toy, GameLevel> getToyAndLevelOfSpatial(Spatial spatial)
{
Toy toyWithSpatial = firstValue;
GameLevel levelToyFound = secondValue;
HashMap<Toy,GameLevel> hm=new HashMap<>();
hm.put(toyWithSpatial, levelToyFound);
return hm;
}
private void findStuff()
{
HashMap<Toy, GameLevel> hm = getToyAndLevelOfSpatial(spatial);
Toy firstValue = hm.keySet().iterator().next();
GameLevel secondValue = hm.get(firstValue);
}
You even have the benefit of type safety.
Return an Array Of Objects
private static Object[] f ()
{
double x =1.0;
int y= 2 ;
return new Object[]{Double.valueOf(x),Integer.valueOf(y)};
}
In my opinion the best is to create a new class which constructor is the function you need, e.g.:
public class pairReturn{
//name your parameters:
public int sth1;
public double sth2;
public pairReturn(int param){
//place the code of your function, e.g.:
sth1=param*5;
sth2=param*10;
}
}
Then simply use the constructor as you would use the function:
pairReturn pR = new pairReturn(15);
and you can use pR.sth1, pR.sth2 as "2 results of the function"
You also can send in mutable objects as parameters, if you use methods to modify them then they will be modified when you return from the function. It won't work on stuff like Float, since it is immutable.
public class HelloWorld{
public static void main(String []args){
HelloWorld world = new HelloWorld();
world.run();
}
private class Dog
{
private String name;
public void setName(String s)
{
name = s;
}
public String getName() { return name;}
public Dog(String name)
{
setName(name);
}
}
public void run()
{
Dog newDog = new Dog("John");
nameThatDog(newDog);
System.out.println(newDog.getName());
}
public void nameThatDog(Dog dog)
{
dog.setName("Rutger");
}
}
The result is:
Rutger
You can create a record (available since Java 14) to return the values with type safety, naming and brevity.
public record MyResult(int number1, int number2) {
}
public static MyResult something() {
int number1 = 1;
int number2 = 2;
return new MyResult(number1, number2);
}
public static void main(String[] args) {
MyResult result = something();
System.out.println(result.number1() + result.number2());
}
First, it would be better if Java had tuples for returning multiple values.
Second, code the simplest possible Pair class, or use an array.
But, if you do need to return a pair, consider what concept it represents (starting with its field names, then class name) - and whether it plays a larger role than you thought, and if it would help your overall design to have an explicit abstraction for it. Maybe it's a code hint...
Please Note: I'm not dogmatically saying it will help, but just to look, to see if it does... or if it does not.

Categories