Java: Using an enum as an array reference - java

I would like to reference an array with an enum type. This is a pretty standard thing in C++ (my origin), however I'm unsure if this is possible/desirable in Java.
For example, I would like to have an enum such as:
public enum Resource {
COAL,
IRON
}
Then later I would like to reference like this:
Amount[COAL] // The amount of coal
Price[IRON] // The price of iron
I don't want to make Amount and Price fields of Resource as I would like a list of objects (orders for resources) grouped by the resource type. Manually assigning an int to each type of Resource is no better than public static int final BLAH I feel, nothing gained.
In essence, I'm looking for the enum of C++ which tags things. I realise that this could be the 'wrong' way of doing things in Java, so feel free to point me in the direction of the correct Java ethos.

In C++, an enum is effectively an alias for an integer. In Java, they're "proper" objects - which is why you can't use them as an array reference.
If you want to look up the value in your array that's associated with a particular enum object - that sounds like a Map to me! How about replacing those arrays with an EnumMap<Resource, Double>?
The EnumMap class is optimised for use with enum keys, such that it does end up using an array keyed on the enums' ordinal (integer) value behind the scenes. So it's much faster than a general-purpose hashmap, and you get the speed of an array-based solution with the semantic expressiveness of a Map - it's the best of both worlds.

You can do almost it. In contrast to C++ where enum is just an int, Java's enum is class. So you can't use it as an index of array. But every enum element has ordinal() that is int, so you can say
amount[COAL.ordinal()]
price[IRON.ordinal()]
But you have a better approach. Can add methods to enum, so it will look like:
IRON.price(amounts)
COAL.amount(prices)
I think this approach is much better.

Each Java enum element has an ordinal associated with it, indexed from zero based on the order of definition in the enum. Just use e.g.
COAL.ordinal()
However, it sounds to me like you'd be better off creating a class e.g. Order with fields for Amount and Price and then keeping a collection of those e.g. in a Map indexed by the enum elements.
e.g.
Map<Resource, Order> orders = new HashMap<Resource, Order>();
orders.put(Resource.COAL, new Order(price, amount));

I think you're looking for EnumMap, http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html
It's not exactly an array, but because the key is an enum, it's still space efficient.
It ends up like:
amount.get(Resource.COAL)

Maps are very good for more dynamic data. But you also have to code all the checking for double names, double values, existing names/values and all the stuff. And even in this case if you do the error, it will be found at runtime only.
For more static data better use not primitive enums, but new type enums from Java 6. They are excellent! And errors will be found by compiler.
public enum Resource{
COAL(0), IRON(1);
int index;
private Resource(int index){
this.index=index;
}
}
...
amount[Resource.COAL.index]=...
But better variant is:
public enum Resource{
COAL(538,0.5f), IRON(115,1.5f);
int amount;
float price;
private Resource(int amount, float price ){
this.amount=amount;
this.price=price;
}
}
...
Resource.COAL.amount=...
You can use their name.
You could make the cycle through all enum:
for(Resource resourceType: Resource.values()) {
String toOutput=resourceType.name()+" amount="+ resourceType.amount;
}

Unfortunately, you'll need a slightly longer syntax:
Amount[COAL.ordinal()] // The amount of coal
Price[IRON.ordinal()] // The price of iron
If that is not to your liking, constants may be your only option, i.e.
public class Resource {
public static final int COAL = 0;
public static final int IRON = 1;
}
Hope that helps.

Related

choosing vector legacy class over array list

In an interview I was being asked by two questions that are..
When does practically we require the use of vector..?
As per my analysis synchronization is the main reason but they were intrested to know that apart from synchronization what are the other practical reasons that we may prefer the use of vector.
Please advise that apart from synchronization what are the other various reason that we will choose vector legacy collection..!
One difference I can think of is Vector supports Enumeration.You can get create Enumeration easily by calling
Enumeration enums = v.elements();
But in case of ArrayList,you need to do like this:
Enumeration enums = Collections.enumeration(arrayList);
Vectors are used in the variable length argument in java.because Vector can automatically expand based on the argument passed to it.
for example
public int sum(int i...)
{
int sum=0;
for(int s:i)
{
sum=sum+s;
}
return sum;
}
in this method I have passed i as an variable length argument no matter how many integer the user will pass to this method ,this method will return the sum based on the user arguments..
so vector provides this facility to the user.
this is where vectors are implemented.Internally the variable length arguments uses Vector to
store the Data.

What's the best way to return a pair of values in Java? [duplicate]

This question already has answers here:
How to return multiple values? [duplicate]
(3 answers)
Closed 3 years ago.
This is a small issue, as I could easily whip up a pair class to do the job. I don't really want to do this though, and I feel like there should be some simple, built-in, java-like way of returning two values. What do you guys is the best, simplest way of doing this? Arrays? Some other data structure?
As far as I know, there is unfortunately no built-in representation of a pair in Java (and I certainly wish there was). Personally, when I code a project where I find that a pair class often would be useful, I create a generic Pair<T, U> class (which is probably what you were thinking of). Returning an array is a fast and simple way, but you might come to regret it later, because people who use your method will wonder whether the method might at some point return more than two values.
Whichever solution you choose: whenever you feel that you need a Pair, you should consider whether the time saved today by using e.g. a generic Pair class really is worth the loss of information to the next person who reads the code (and that person may well be you in six months). Writing a separate class for the return type takes more time now, but it would convey more information to those that use your method (namely, it tells the users what the return value represents, and contains useful member names for the two values). If it is a non-public method that is used only a few places, though, a Pair is more acceptable.
Using a container class is the easiest way.
public class Pair<T, U> {
public final T t;
public final U u;
public Pair(T t, U u) {
this.t= t;
this.u= u;
}
}
The closest thing I've seen to a "pair" in the standard libraries are the Map.Entry interface and the AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry classes that implement it.
If both objects are the same class an array is easier to use.
Apache Commons Lang3 provides an abstract Pair class with a couple implementations including ImmutablePair and MutablePair.
Three approaches, all not so great:
Roll your own Pair<A, B>. You said you didn't want to do that.
Return a Object[]. This is not type safe.
Mimic out variables or pointers by supplying single element arrays as parameters.
An example of #3:
public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) {
assert lastName != null && lastName.length == 1;
assert firstName != null && firstName.length == 1;
assert dob != null && dob.length == 1;
...
}
The third option makes life painful for the caller.
So like I said, no nice solution.
As an aside, Scala uses various Tuple classes (up to 21-tuple, from what I remember) to help you with this.
There is a pair class in JavaFX, but you shouldn't use it. What you SHOULD use is something like this:
// We've skipped imports and package declarations
public final class YourClass {
/* Assume there is a bunch of stuff here */
// I don't know what method you're using, so forgive the silly example
public YourClass.Pair sillyExampleOfPairs(String someString) {
return new YourClass.Pair(someString, someString.length() * 13);
}
#Value // Lombok annotation.
public static class Pair {
String text;
int integer;
}
// this is an even more succinct possibility
#Value public static final class ShorterPair {String text; int integer}
}
While the name Pair here is obviously not that well chosen, and you should choose a more descriptive name, the obvious ways this will work (the fields are final private and you have a getter on each, because of the annotation), should not be lost on you. And while yes, this is slightly more wordy than using Pair, it's much more robust. What if you do need to add an extra parameter to the return value? You "only" need to change this class then. And you can update all the relevant JavaDocs immediately, which is also nice. If you have to change types, they would both entail similar amounts of work.
As long as you're only adding stuff, the old getText() and getInteger() methods would keep working as they did before. You also avoid having to add Yet Another Dependency to your projects. It's not a big win. Having Pair available is nice for prototyping, but it's not nice for later.
My final theoretical CS-y argument is that Pair is the same type as Pair. But if you have a Phonebook.Entry (with String and int) and say, Inventory.Item (with a name and a number of items we currently have inventoried), these two are very distinct types, which do very distinct things. You can't put one into the other. This is a Good Thing.
It's also much clearer for us poor bastards that have to go and debug your systems to see something like "com.name.project.something.something.Phonebook.Entry" in a stack trace than "org.apache.commons.lang3.tuple.Pair". One of these tells me WHAT I'm supposed to be looking at, and gives me some info on WHY I'm seeing a pair. The other says... nothing.
Now you might not care that you have to type for 3 extra seconds to save me 3 minutes. But I choose to believe in the goodness of your heart, and the nobility of your soul. Therefore, do the right thing.
Write a small static class instead.
I have been told by experts that when faced with the question of pairs, one of two things is true:
You need to rethink your structure (this blunt answer doesn't help anyone)
You need to build your own class to hold the pair
I would suggest that the second case is not all that abnormal. However, if what you are doing seems too trivial for introducing a new class, then using a Map could work, as others have suggested. If you are simply sending a single response back, then a Map seems like a bit much.
If a list of pairs sounds like it would work, and you need to maintain order, you could try a LinkedHashMap so that order is maintained.
if both are integers then I would advise a java.awt.Point but otherwise just create a container class with two objects x and y
Some observation of mine:
Array is bulit-in, fast and easy to use, although imposible to expand its capacity. What if you want 3 values to be returned after 3 months?
ArrayList/other colletions can be good, allows you to increment the capacity(initially 10).
Note that Vector can be overkill in comparison to ArrayList when you only want to store 2 values to be fetched later. Map also can be good because it's always sorted and ordered.
Some user-defined class: maybe an option if is meaningful(means that the data returned is important-ish to be a Java Bean), and you want to store more than just 2 integers into it. Readibility is better in case you add more notes in its Javadoc. Can be expanded as you like, just add fields in this class. Slower, but safer.

Is there a a C-like way to get item number from enum in java?

Perhap this is a simple basic question
Having an enum
public enum TK{
ID,GROUP,DATA,FAIL;
}
Can I get the order number for example ID=0, GROUP=2, DATA=3, FAIL=4 ?
This is a way to to that, but a weird and long one! =S
public enum TK{
ID(0),GROUP(1),DATA(2),FAIL(3);
int num;
TK(int n)
{
this.num=n;
}
public int get()
{
return num;
}
};
to get numbers so I write TK.ID.get(), TK.GROUP.get(), etc... I don't like that
there is a better way?
( C enums, C macros..I miss you both )
thanks
The ordinal() does what you want to do. This is an excerpt from the documentation:
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.
Josh Bloch in Effective Java 2nd Edition goes further to explain why using ordinal() is a terrible idea. Here are some quotes, slightly edited:
Never derive a value associated with an enum from its ordinal; store it in an instance field instead. (Item 31: Use instance fields instead of ordinals) It is rarely appropriate to use ordinals to index arrays: use EnumMap instead. The general principle is that application programmers should rarely, if ever, use Enum.ordinal. (Item 33: Use EnumMap instead of ordinal indexing)
Your "weird and long" way is precisely the prescription of Item 31.
Fortunately, Java is not C. A Java enum is very powerful and flexible, supported by many library classes, and you should learn to embrace them instead of using ordinal().
Have a look at EnumMap for example.
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum Maps are represented internally as arrays. This representation is extremely compact and efficient.
That is, instead of the following (which is perhaps what you wanted to do):
T[] arr = ...;
TK tk = ...;
T something = ...;
arr[tk.ordinal()] = something;
You can instead do:
Map<TK,T> map = new EnumMap<TK,T>(TK.class);
TK tk = ...;
T something = ...;
map.put(tk, something);
The book also covers another "traditional" (ab)use of enum in C, i.e. bit fields (assigning powers of 2 to each constant etc). Well, for that Java has EnumSet instead.
Are you looking for ordinal?
You can use ordinal()
tk.ordinal()
is the way to do it where tk is an instance of TK
http://java.sun.com/javase/6/docs/api/index.html?java/lang/Enum.html#ordinal()
http://java.sun.com/javase/6/docs/api/java/lang/Enum.html#ordinal()
public final int ordinal()
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

java: how do I create an array of tuples

how can I create an array of tuples in jsp (java)
like
(a:1, b:2)
(c:3, d:4)
...
...
Create a tuple class, something like:
class Tuple {
private Object[] data;
public Tuple (Object.. members) { this.data = members; }
public void get(int index) { return data[index]; }
public int getSize() { ... }
}
Then just create an array of Tuple instances.
if you want an arbitrary size tuple, perl hash style, use a Map<K,V> (if you have a fixed type of keys values - your example looks like Map<Character,Integer> would work - otherwise use the raw type). Look up the java collections for more details about the various implementations.
Given those tuples, if you want to stick them in an sequential collection, I'd use a List (again, look up the collections library).
So you end up with
List<Map<K,V>> listOfTuples
if you need something more specific (like, you'll always have x1, x2, x3 in your tuple) consider making the maps be EnumMaps - you can restrict what keys you have, and if you specify a default (or some other constraint during creation) guarantee that something will come out.
There's no default pair / n-tuple class in Java; you'd have to roll your own.
you could use the HashSet class.
If you are dealing with tuples of fixed size, with fixed names of the attributes, define a simple data class of your own, and then define the array of this class.
If on the other hand you want the attribute names to be flexible and determined at runtime, use a Map structure. In your example above, it seems like HashMap<String,Integer> can do the job. You may want to wrap it in order to reduce its functionality, and maybe also add more specific functionality.
I know I am late to the party but an array of points should do the job.
Check here to see the documentation about points.

Java: How do I implement a method that takes 2 arrays and returns 2 arrays?

Okay, here is what I want to do:
I want to implement a crossover method for arrays.
It is supposed to take 2 arrays of same size and return two new arrays that are a kind of mix of the two input arrays.
as in [a,a,a,a] [b,b,b,b] ------> [a,a,b,b] [b,b,a,a].
Now I wonder what would be the suggested way to do that in Java, since I cannot return more than one value.
My ideas are:
- returning a Collection(or array) containing both new arrays.
I dont really like that one because it think would result in a harder to understand code.
- avoiding the need to return two results by calling the method for each case but only getting one of the results each time.
I dont like that one either, because there would be no natural order about which solution should be returned. This would need to be specified, though resulting in harder to understand code.
Plus, this will work only for this basic case, but I will want to shuffle the array before the crossover and reverse that afterwards. I cannot do the shuffling isolated from the crossover since I wont want to actually do the operation, instead I want to use the information about the permutation while doing the crossover, which will be a more efficient way I think.
My question is not about the algorithm itself, but about the way to put in in a method(concerning input and output) in Java
Following a suggestion from Bruce Eckel's book Thinking in Java, in my Java projects I frequently include some utility classes for wrapping groups of two or three objects. They are trivial and handy, specially for methods that must return several objects. For example:
public class Pair<TA,TB> {
public final TA a;
public final TB b;
/**
* factory method
*/
public static <TA,TB> Pair<TA,TB> createPair(TA a,TB b ){
return new Pair<TA,TB>(a,b);
}
/**
* private constructor - use instead factory method
*/
private Pair(final TA a, final TB b) {
this.a = a;
this.b = b;
}
public String toString() {
return "(" + a + ", " + b + ")";
}
}
Read the last section of this article:
http://www.yoda.arachsys.com/java/passing.html
To quote:
This is the real reason why pass by
reference is used in many cases - it
allows a method to effectively have
many return values. Java doesn't allow
multiple "real" return values, and it
doesn't allow pass by reference
semantics which would be used in other
single-return-value languages.
However, here are some techniques to
work around this:
If any of your return values are status codes that indicate success or
failure of the method, eliminate them
immediately. Replace them with
exception handling that throws an
exception if the method does not
complete successfully. The exception
is a more standard way of handling
error conditions, can be more
expressive, and eliminates one of your
return values.
Find related groups of return values, and encapsulate them into
objects that contain each piece of
information as fields. The classes for
these objects can be expanded to
encapsulate their behavior later, to
further improve the design of the
code. Each set of related return
values that you encapsulate into an
object removes return values from the
method by increasing the level of
abstraction of the method's interface.
For instance, instead of passing
co-ordinates X and Y by reference to
allow them to be returned, create a
mutable Point class, pass an object
reference by value, and update the
object's values within the method.
As a bonus, this section was updated by Jon Skeet :)
If it is reasonable for the caller to know the size of the returned arrays ahead of time, you could pass them into the method:
public void foo(Object[] inOne, Object[] inTwo, Object[] outOne, Object[] outTwo) {
//etc.
}
That being said, 90+% of the time multiple return values out of a method are hiding a better design. My solution would be to make the transformation inside an object:
public class ArrayMixer {
private Object[] one;
private Object[] two;
public ArrayMixer(Object[] first, Object[] second) {
//Mix the arrays in the constructor and assign to one and two.
}
public Object[] getOne() { return one; }
public Object[] getTwo() { return two; }
}
I suspect that in your real use case that class and array one and array two can get better names.
Since the specification of your method is that it takes two input arrays and produces output arrays, I agree with you that the method should return both arrays at the same time.
I think that the most natural choice of return value is an int[][] of length 2 (substitute int with whatever type you are using). I don't see any reason it should make the code harder to understand, especially if you specify what the contents of the return value will be.
Edit: in response to your comment, I understand that you have considered this and I am saying that despite your stylistic objections, I don't believe there is a strictly "better" alternative ("better" here being loosely defined in the question).
An alternative approach, largely equivalent to this one, would be to define an object that wraps the two arrays. This has the small distinction of being able to refer to them by names rather than array indices.
The best way to do it would be to do
public void doStuff(int[] array1, int[] array2) {
// Put code here
}
Since Java arrays in Java pass the reference, any modifications made to the arrays will be made to the array itself. This has several caveats
If you are setting it to null you must use a different way (such as encapsulating it in an object)
If you are initializing the array (in the method), you must use a different way
You would use this in the format:
// other method
int[] array1 = new int[20]; // the arrays can be whatever size
int[] array2 = new int[20];
doStuff(array1,array2);
// do whatever you need to with the arrays
Edit: This makes the assumption that it is okay to make changes to the input arrays.
If it isn't, then an object (such as in leonbloy's answer is definitely what is called for).
You strictly cannot return more then one value (think object or primitive) in Java. Maybe you could return an instance of a specific "Result" object which has the two arrays as properties?
You could pass the output arrays as parameters to the method. This may give you more control over memory allocation for the arrays too.
The cleanest and easiest to understand way would be to create a container bean that contains two arrays, and return the container from the method. I'd probably also pass in the container into the method, to keep it symmetric.
The most memory efficient way, assuming both arrays are the same length, would be to pass a multidimensional array - Object[2][n] - where n is the length of the arrays.
If you're really against the arbitrary ordering that comes from a 2d array or a collection, perhaps consider making an inner class that reflects the logic of what you're doing. You could simply define a class that holds two arrays and you could have your method return that, with names and function that reflect the logic of exactly what you're doing.
A simple solution to the above problem is to return as Map.The trick of this question is how you will define the keys to identify the objects, let say there are two
input arrays [a,a,a,a] [b,b,b,b] and two outputs arrays [a,a,b,b] [b,b,a,a]
For that you can use String variable as a key just to identify objects because String variable is immutable, so they can be used as keys.
And as example
Map<String,String[]> method(String[] x,String[] y){
do your stuff..........
Hashmap<String,String[]> map =new HashMap<String,String[]>();
map.put("Object2",[b,b,a,a]);
return map;
}

Categories

Resources