How to determine lowest/highest index of enum in java? - java

Suppose there is the enum declaration somewhere in code:
enum Colors { RED(100), BLUE(200); }
Can I get the lowest/highest index value for that particular enum type presuming I am not aware of the declaration? Is it possible in java?
Example:
int lowIndex = Colors.minIndex(); // should return 100
Thanks everyone. So there are no implicit methods to query for min/max defined integer value. I'll have to iterate through the enum values and determine it from there as you have described.

You'll have to iterate over the enum set:
for (Color p : Color.values()) {
// keep track of min "index"
}
Remember that an enum is essentially collection of predefined object instances. RED(100) is calling the Color(int value) constructor. That said, I could make a color enum with values defined like this:
RED("best", 14, 3.33546)
Hence, the logic for finding the minimum "index" will be different case by case.

With index do you mean the ordinal or the integer values given in the enum ?
Anyways this is a simple example that may help you:-
enum Mobile {
Samsung(400), Nokia(250),Motorola(325);
int price;
Mobile(int p) { //values in brackets are set to price property in enum
price = p;
}
int showPrice() {
return price; //you have to declare methods in enum to return value, there is no predefined function like returnValue()
}
}
public class EnumDemo {
public static void main(String args[]) {
System.out.println("CellPhone List:");
for(Mobile m : Mobile.values()) {
System.out.println(m + " costs " + m.showPrice() + " dollars");
}
Mobile ret = Mobile.Samsung;
System.out.println("The ordinal is = " + ret.ordinal());
System.out.println("MobileName = " + ret.name());
}
}
Note that the java.lang.Enum.ordinal() method returns the ordinal of the enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).
And the output is:-
CellPhone List:
Samsung costs 400 dollars
Nokia costs 250 dollars
Motorola costs 325 dollars
The ordinal is = 0
MobileName = Samsung

You can't override an enum's 'index'. What's happening here is that the Colors enum has a constructor that takes an int as a parameter. It's up to the implementation of the constructor to store that value.
You could maintain a static map of these values, updated by the enum constructor, that could be queried for min/max values.
Alternatively you could just look over all the enums every time looking for the min/max:
int max = Integer.MIN_VALUE;
for (Colors c in Colors.values())
max = Math.max(c.getIndex(), max);

What about this? It "caches" the value when the enum is loaded.
public enum Color {
RED(100),
BLUE(200);
public final int val;
private Color(int val) {
this.val = val;
if (Dummy.maxColor == null || Dummy.maxColor.val < val) {
Dummy.maxColor = this;
}
}
// This seems to be needed because you can't access static fields in enum constructors
private static class Dummy {
private static Color maxColor = null;
}
public static Color getMaxColor() {
return Dummy.maxColor;
}
}

Related

Java method that produces an object

I have to follow the below UML diagram to design a programme.
The programme is supposed to generate 2 random integers, and ask user for input the answer to the sum of said integers.
However, I am not sure how to make use of the method static void getTwoIntegers(MyInteger m, MyInteger n) , or what to put inside it.
I have tried initialising 2 MyInteger objects with MyInteger int_1 = new MyInteger(m); and (n) in this method, but get a "cannot be resolved" error everytime I call its getter method int_1.getInteger();
And since the method getTwoIntegers is void, I cannot just return 2 random integers. I'm truly stuck on how to utilise this method
Any ideas? Thanks so much
Simple demo of what your implementation can accomplish.
The MyInteger objects passed as parameters (m and n) can be modified by the implementation of getTwoIntegers using the setInteger method of the class.
public class Main
{
public static void main(String[] args) {
MyInteger a = new MyInteger(333);
MyInteger b = new MyInteger(444);
System.out.println("before: " + a.getInteger() + "," + b.getInteger());
getTwoIntegers(a,b);
System.out.println("after: " + a.getInteger() + "," + b.getInteger());
}
public static class MyInteger {
private int val;
public MyInteger() { val = 0; }
public MyInteger(int v) { val = v; }
public void setInteger(int n) { this.val = n; }
public int getInteger() { return val; }
}
static void getTwoIntegers(MyInteger m, MyInteger n) {
// in your case modify implementation to produce random numbers
m.setInteger(222);
n.setInteger(555);
}
}
Prints:
before: 333,444
after: 222,555
Gardener's answer nailed it. For the records, I'd like to share some more thoughts.
This class diagram is misleading. The parameters of an UML operation have a direction that should be indicated in front of the parameter name. It can be in, out, inout. If the direction is omitted in the diagram, UML assumes that it's an in argument. Which assumes that the parameter is not muted by the operation.
If it would have been correctly specified as getTwoIntegers(out m: MyInteger, out n: MyInteger) (yes, UML syntax order is slightly different from Java), you would have understood that the values of m and n are provided for the output of the values of the operation, and not as input. And indeed, as Gardener explained, in Java you can provide a class object that can then be mutated to store the results; because class objects are passed by reference (i.e. it's the same object that is used and not a copy). This is by the way why a class MyInteger is used in this lab instead of a built-in type int.
Other unrelated UML remarks: there is no static type modifier keyword in UML. Either is it marked as {static} or is it underlined. Last but not least, there should be no multiplicity on a dashed dependency arrow. Multiplicities are for associations, i.e. structural relationships.

compareTo() method using float attribute of object. How is it used, and why?

The code from my class, I don't understand it totally. I read on internet that compareTo() method is used for comparing strings to strings and objects to strings,but in my code it is used to compare float to strings, I guess?! Can you explain how is used comparedTo() method in the code below and why do we use it in our case?
package ro.ase.acs.classes;
import ro.ase.acs.interfaces.Mobility;
//Comparable is a generic interface; click add unimplemented methods ; the method will appear at the end of the class
public final class Car extends Vehicle implements Mobility, Cloneable,Comparable<Car> {
public static final int maxNbOfKm = 1_000_000;//it is static, in order to acces it use .
private EngineType engineType;
private float speed;
public Car() {
super();
engineType = EngineType.gas;
speed = 0;
}
public Car(String _name, EngineType _engineType, float _speed) {
super(_name, true);
engineType = _engineType;
speed = _speed;
}
#Override
public void Start() {
System.out.println("The " + engineType.toString() +
" car has started!");
}
#Override
public void Stop() {
System.out.println("The " + engineType.toString() +
" car has stopped!");
}
#Override
public void DisplaySpeed() {
System.out.println(String.format("The %s car runs with %f km/h",
engineType.toString(), speed));
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("The car named ");
sb.append(name);
sb.append(" has a(n) ");
sb.append(engineType.toString());
sb.append(" engine and is running with ");
sb.append(speed);
sb.append(" km/h");
return sb.toString();
}
#Override
public Object clone() throws CloneNotSupportedException {
Car c = (Car)super.clone();
c.engineType = engineType;
c.speed = speed;
return c;
}
#Override
public boolean equals(Object obj) {
if(!(obj instanceof Car)) {
return false;
}
else {
Car c = (Car)obj;
return name.equals(c.name);
}
}
#Override
public int hashCode()
{
return 31*name.hashCode()+13*(HasEngine()?1:0)+7*engineType.hashCode()+(int)speed*100;
}
public enum EngineType { gas, diesel, electric, hybrid }
#Override
public int compareTo(Car o) {
if(speed==o.speed)
{return 0;}
else if (speed>o.speed)
{
return 1;
}
else
{return -1;}
}
// public final int hashCode() {
// return engineType.hashCode();
// };
}
The contract of the Comparable interface, respectively the compareTo() method is:
it returns 0 when both objects are considered "the same" from an ordering perspective
it returns -1 respectively +1 (to be precise any negative or positive value) to indicate when the "other" object is less respectively greater than "this" object.
In other words: the method provides a mean to define a natural order of objects that can be ordered.
If ordering cars by their speed actually makes sense is a completely different story. I would argue that: no, that doesn't make sense. If at all, you could/should define external Comparator objects that define different ways of "ordering" cars, and then a SpeedComparator would obviously order by speed (but in an explicit way).
It doesn't matter what you compare, you can resolve which comes first and which second by what you define. In compareTo methods, -1 means that it comes first and the element you compare it to, comes after that. 1 means that it comes after the element and 0 means they are equal and doesn't get rearranged.
If speed is bigger then it comes later in your list, if it's smaller it comes after. Strings are compared by length for example, if you do "Chicken".compareTo("Cow") then chicken comes after.
compareTo() method is used to sort object of a specific class.
In your case it compares Car objects by value of their speed property.
So you can use it to sort list (or array) of Car objects by values of their speed property.

Java array[2] reference to array[0] but serialNo increments1

I have a java program that models a tv and has stuff like power, channel, volume etc. It also has a unique Serial number that is automatically set (increments 1)
However, for my last array item array[2] I need to referernce my array[0] doing this works but my serialNo is no longer unique and just increments 1 (acts like a new tv has been created)
I think your problem lies in the usage of
public static int serialNo() {
return serialNo++;
}
Each time you call this method, you increment the content of the static field.
There is no direct relation between a TV and its serial number.
I suggest that you create a private field serialNumber in the TV class and assign e.g. in the constructor serialNo to serialNumber and then increment.
serialNo is static member of Tv class, this is what Oracle's documentation says about statics.
Fields that have the static modifier in their declaration are called
static fields or class variables. They are associated with the class,
rather than with any object. Every instance of the class shares a
class variable, which is in one fixed location in memory. Any object
can change the value of a class variable, but class variables can also
be manipulated without creating an instance of the class.
In this case, serialNo is not really associated with any object. So, there won't be something like serialNo of the reference at array[2] in this code.
Now, coming back to the question, you have a for loop that increments serial number as shown below:
for (int i = 0; i < tvDetails.length; i++) {
System.out.println(SERIAL_NO + "\t\t" + tvDetails[0].serialNo() + "\n");
It executes tvDetails.length times (3) ad hence, the number gets incremented. If you don't want it to be incremened there then you need to make a couple of changes:
Remove return serialNo++; from serialNo() method and just return serialNo:
public static int serialNo() {
return serialNo;
}
Increment serialNo in Tv's constructor, e.g.:
public Tv(boolean tvPower, int channel, int volumeLevel) {
this.tvPower = tvPower;
this.channel = channel;
this.volumeLevel = volumeLevel;
serialNo++;
}
The problem is here:
public static int serialNo() {
return serialNo++;
}
This violates the SRP, the Single Responsibility Principle, by doing four things:
* Initializes an instance's serialNo,
* Generates a global "next serial no",
* Reports the global serial no, and
* Reports the instance's serial no, impossible for a static member.
Don't use the same name for different things.
public class Tv {
private static int universalSerial; // not thread-safe
public static int getUniversalSerial() {
return universalSerial;
}
static int dispenseUniversalSerial() {
return universalSerial++;
}
private final int serial;
public Tv () {
this.serial = dispenseUniversalSerial();
}
public int getSerial() {
return serial;
}
#Override public boolean equals(Object other) {
if (this == other) { return true; }
if (! (other instanceof Tv)) { return false; }
Tv otherTv = (Tv) other;
return serial == otherTv.serial;
}
#Override public int hashCode() {
return serial;
}
#Override public String toString() {
return "Tv " + serial;
}
}
Notice how the four tasks are split up between static and instance behaviors. Notice how the different names label different things. Notice the elimination of name parts like No that indicate implementation. Notice the coordinated overrides of the Big Three methods, equals, hashCode, and toString. Notice the lack of override for the fourth member of the Big Three, compareTo. That's deliberate. Notice the lack of thread safety. Notice that the instance serial field is final.
All of those decisions have purpose, and are boilerplate for value classes. The example implementation here is bog standard for non-thread-safe, non-comparable value classes with a factory. You should be able to code one of these up in about 10 minutes. It's a great kata to practice it.

Java: Dynamically cast Object reference to reference's class?

Is it possible to cast a variable using a different variable instead of using the name of a class?
Here is functioning code:
Object five = new Integer(5);
int six = (Integer) five + 1;
I would love to replace that second line with
int six = five + 1;
but I can't, so could i do something like one of these alternatives:
int six = (foo) five + 1;
int six = foo(five) + 1;
int six = foo.cast(five) + 1;
??
why i want to do this
I have a Map with keys of a custom enum, and with values of type String, Integer, Double, etc.
I would like to perform class-specific operations on map entry values without hard-coding the cast class.
example
enum keyEnum { height, color; }
public static void main(String[] args) {
Map<keyEnum, Object> map= new HashMap();
String value1 = "red";
Double value2 = 3.2;
map.put(keyEnum.color, value1);
map.put(keyEnum.height, value2);
double x = (Double) map.get(keyEnum.height) + 10.5;
}
I would really like to avoid having to hard-code that (Double) in the last line. Have found no solutions so far, only indications that it might not be possible.
I'm using this setup for a program that needs to write and read and write large csv files. I would like a way for Java to automatically cast variables appropriately so I don't have to remember or code the class of every column type.
I have an enum of all the column titles which i use as keys for maps that store the column's variables. This is to avoid hard-coding the array index for each column (after row.split(",")) which is a maintenance nightmare. I'm open to better approaches to this
You are not using Java as it was intended so it's going to be slow, unsafe and ugly. What you should do is
class MyType { double height; String color; }
public static void main(String[] args) {
MyType mt = new MyType();
mt.color = "red";
mt.height = 3.2;
double x = mt.height;
// to iterate over the fields
for(Field field: MyType.class.getDeclaredFields()) {
System.out.println(field.getName() + "= "+ field.get(mt));
}
}
This will be much safer with compile time checks, use less code and it will use far less memory and CPU.
Store the classtype in a variable, and leverage the cast method.
Class<T> cls and cls.cast()

Java cast Long to Enum type issue

I had a little problem with casting Java long type to Enum type and can't find a solution how to do that.
Here is what I'm using :
public enum DataType {
IMAGES(1),
VIDEOS(2);
private int value;
private DataType(int i){
this.value = i;
}
}
and I need to do something like this:
DataType dataType;
String thiz = "1";
long numb = Long.parseLong(thiz);
dataType = numb;
The error that I get says:
Convert numb to DataType or convert dataType to long.
Second Scenario:
I have this :
static String[] packetType;
String tmp=incomingData.toString(); // where incomingData is byte[]
int lastLoc = 0;
int needsSize = packetFieldSizes[tmpCurrentField-1]; // where packetFieldSizes,tmpCurrentField are integers.
thiz=tmp.substring(lastLoc, needsSize);
packetType=thiz; // packetType = thiz copy; where thiz is the same as used above.
I tried to convert thiz to String[] and use valueOf,but
Any suggestions how to get the thinks to work?
Thanks in advance!
Enum already provides a unique integer for each of it's instances. Check out ordinal(). (Note that it's zero-based though.)
If you need to go from a long to a DataType you can do
DataType dataType;
String thiz;
long numb = Long.parseLong(thiz);
dataType = DataType.values()[(int) numb];
A complete list of conversions from and to enum constants, strings and integers can be found in this answer:
Conveniently map between enum and int / String
If for some reason you need to assign the numbers yourself and thereby can't use aioobe's good solution, you can do something like the following:
public enum DataType {
IMAGES(1),
VIDEOS(2);
private final int value;
private DataType(int i){
this.value=i;
}
public static DataType getByValue(int i) {
for(DataType dt : DataType.values()) {
if(dt.value == i) {
return dt;
}
}
throw new IllegalArgumentException("no datatype with " + i + " exists");
}
The static method getByValue() searches for the DataType with the provided number.
In addition to #aioobe's answer, you could roll your own getInstance method. This would provide more flexibility, since you wouldn't be dependent on the ordinal.
public enum DataType {
.
.
public static final DataType getInstance(final int i){
for(DataType dt: DataType.values()){
if(dt.value == i){
return dt;
}
}
return null;
}
}
Correct answer from aioobe. Maybe some other concerns ?
You could be better of using int instead of long, for the enum index.
It could be like :
String indexAsString;
int index = Integer.parseInt(indexAsString)-1;
DataType dataType = DataType.values()[index];
Please note the "-1", as arrays are zero-based while your index is one-based.
ordinal() will work if the numbers you are passing to the enum are indexes and not some arbitrary code, like resolution or number of chars in a line.
I'd extends the enum with an accesor method for the value, a resolution index and a static method that resolves a number into a Enum value. Here you go...
public enum DataType {
IMAGES(1),
VIDEOS(2);
private int value;
DataType(int i){
this.value=i;
}
static final Map<Integer,DataType> inverseIndex;
static {
inverseIndex = new HashMap<Integer,DataType> ();
for (DataType dt:DataType.values()) {
inverseIndex.put(dt.getValue(), dt);
}
}
public int getValue() {
return value;
}
public static DataType resolve(int number) {
return inverseIndex.get(number);
}
}
Note that this solution won't work is your map Enum-value is not bijective, so you may only have distinct values for the enums in your enumType.

Categories