Related
I have this bugging problem I cannot figure out. I have this exercise:
Complete the following generic Pair class, so that execution of the
program gives the indicated output. Do not change main.
class Pair ... { ... }
class GenericPairTest {
public static void main(String[] args) {
Pair<String,Integer> phoneNumber = new Pair<>("Bill's number", 1324);
System.out.println(phoneNumber);
Pair<Double,Double> point = new Pair<>(3.14, 2.32);
System.out.println(point);
}
}
The output is suposed to be like that:
Bill's number 1324
3.14 2.32`
I tried doing this:
import java.util.*;
class Pair <T,U> {
ArrayList<T,U> newList = new ArrayList<>();
Pair(T inT, U inU){
newList.add(inT,inU);
}
}
class GenericPairTest {
public static void main(String[] args) {
Pair<String,Integer> phoneNumber =
new Pair<>("Bill's number", 1324);
System.out.println(phoneNumber);
Pair<Double,Double> point =
new Pair<>(3.14, 2.32);
System.out.println(point);
}
}
But it doesn't work :(
Why do you need a list? You just need to store the two objects:
class Pair <T,U> {
private T _t;
private U _u;
public Pair(T t, U u) {
_t = t;
_u = u;
public String toString() {
return _t + " " + _u;
}
}
You don't need the ArrayList in your Pair class.
Just keep the two values as two generic members.
You are looking for this I think:
ArrayList<Pair<T,U>>
but I think you should create an internal Pair class which might look something like this:
public class Pair<T, U> {
private T left;
private U right;
// getters/setters + constructor for them
}
You can use a Map as well like the others pointed out but you don't need an ArrayList.
You can't do that with ArrayList, but since your pair always holds exactly two objects, it really doesn't need to store them in a list. Just use two fields:
class Pair<T,U> {
final T t;
final U u;
Pair(T t, U u) {
this.t = t;
this.u = u;
}
#Override
public String toString() {
return t + " " + u;
}
}
The way you're using the ArrayList there is very suggestive of a Map. For example, you could write:
Map<T,U> map = new HashMap<>();
Pair(T t, U u) {
map.put(t, u);
}
But since a map can hold any number of key-value pairs, it is not really the right structure to use for storing a single pair.
If your case, it would be enough to remember the pairs in the Pair class, and not have an internal ArrayList for that.
After that, externally, you can include Pairs in list.
final List<Pair<T,U>> pairList = new ArrayList<>();
Also, sorry to say this, but you're missing some very basic OOP skills here.
So, I am trying to use an enumerated data type as parameter in the place of an object being passed in. I know that a simple switch statement would work but that doesn't really seem elegant to me. I have searched and found that enums can also have actions attached to them but I'm not so clear how to use it in this case or if it is even possible, or if i am just really tired. let me try to use code to explain what I'm asking.
First I have a class with certain fields of other objects that I am basically trying to use the enums to reference. In this case I have a method that acts on one of the fields of trees, because their are multiple trees the method needs to know which tree to act on.
public class bstContactManage()
{
// fields of other objects
BST searchTreeFirstName = new BST(new ComparatorObjOne);
BST searchTreeLastName = new BST(new ComparatorObjTwo);
// and so on and so forth
public boolean modify(Contact contactToFind, BST ToFindIn, String newContactInfo)
{
Contact contUpdate = new Contact(ContactToFind)//save for readdition to tree
contUpdate.update(newContactInfo);
toFindIn.remove(contactToFind);
if(toFindIn.add(contUpdate)) return true;
else return false;
}
}
what I'm wondering or more or less pondering is how to replace the BST parameter with a an enum
i know i could use a switch statement but that doesn't seem any more effective maybe more elegant than passing it an int value and letting it go wild!
so is there a way to get method to look something like
public boolean modify(Contact contactToFind, Enum BSTType, String newContactInfo)
{
Contact contUpdate = new Contact(ContactToFind)//save for readdition to tree
contUpdate.update(newContactInfo);
BSTType.remove(contactToFind);
if(BSTType.add(contUpdate)) return true;
else return false;
}
most of my question stems from the fact that an object such as
bstContactManage man = new bstContactManage()
will be instantiated in another class, and therefore it isn't safe or doesn't seem proper to me to do something like
man.modify(contactIn, man.searchTreeFirstName, "String");
update:
so for more clarification i have another method find which searches a given BST, and currently i am implementing it like this
public List<Contact> find(BinarySearchTree treeUsed, String findThis)
{
//create a new contact with all fields being the same, find is dependent and comparator on tree;
Contact tempContact = new Contact(findThis, findThis, findThis);
return treeUsed.getEntry(tempContact); // where getEntry returns a list of all matching contacts
}
I could do something like
public List<Contact> find(EnumField field, String findThis)
{
BST treeUsed;
switch(Field){
case FIRST:
treeUsed = this.searchTreeFirstName;
break;
cast LAST:
treeUsed = this.searchTreeLastName;
break;
Contact tempContact = new Contact(findThis, findThis, findThis);
return treeUsed.getEntry(tempContact); // where getEntry returns a list of all matching contacts
}
Enum could provide different implementation of its method. A good example would be Math operation:
enum Op {
PLUS {
int exec(int l, int r) { return l + r; }
},
MINUS {
int exec(int l, int r) { return l - r; }
};
abstract int exec(int l, int r);
}
Then I could do Op.PLUS.exec(5, 7) to perform 5 plus 7
See http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html for more detail on how to use enum.
In your case, I wouldn't use enum for something having loads of logic and state, but here is how you could use enum with methods having different implementations.
enum BSTType {
SearchTreeFirstName {
void someMethod(Contact c) {...}
},
SearchTreeLastName {
void someMethod(Contact c) {...}
};
abstract void somemethod(Contact c);
}
public boolean modify(Contact contactToFind, BSTType bstType, String newContactInfo) {
// ...
bstType.someMethod(contact);
// ...
}
By looking at the variable name and class name, I think what you actually meant is indexing Contact in a TreeSet either by first name or last name
enum IndexType implements Comparator<Contact> {
IndexByFirstName {
#Override
public int compare(Contact o1, Contact o2) {
return o1.firstName.compareTo(o2.firstName);
}
},
IndexByLastName {
#Override
public int compare(Contact o1, Contact o2) {
return o1.lastName.compareTo(o2.lastName);
}
};
}
TreeSet<Contact> contacts = new TreeSet<Contact>(IndexType.IndexByLastName);
I know that there isn't way to access to the links of variables in java (like in &C or &php). But for example I have such task:
public class JustTest {
private int n = 1;
private int x = 10;
public int[] getIntegers() {
return new int[] { n, x };
}
public void filledInteger() {
int[] vals = getIntegers();
System.out.println("Before change");
System.out.println(Arrays.toString(vals));
vals[0] = 2;
vals[1] = 20;
System.out.println("After change");
System.out.println(Arrays.toString(vals));
System.out.println("Values of name & xml");
System.out.println(n);
System.out.println(x);
System.out.println("calling getIntegers");
System.out.println(Arrays.toString(getIntegers()));
}
public static void main(String[] args) {
JustTest t = new JustTest();
t.filledInteger();
}
}
The result is:
Before change
[1, 10]
After change
[2, 20]
Values of name & xml
1
10
calling getIntegers
[1, 10]
So, I want to change values of "n" and "x" fields of the class instance. I can't do this by setting straightly (this->n = 20;), because I may dont know what fields do I have. Only method getIntegers knows.
(No in this code, but for example I have child class with its own fields and in the parent class I have a method filledInteger() which should change specified properties of the child class ( he knows about this properties from the method getIntegers which is abstract in the parent class and implemented in the child class))
Here is simple implementation (without inheritance), using links in php
<?php
class JustTest {
private $n = 1;
private $x = 10;
public function getIntegers() {
return array( &$this->n, &$this->x );
}
public function filledInteger() {
$vals = $this->getIntegers();
echo("Before change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
$vals[0] = 2;
$vals[1] = 20;
echo("After change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
echo("Values of n & x". "<br/>");
echo $this->n , "<br/>";
echo $this->x , "<br/>";
echo("call getIntegers again" . "<br/>");
echo(print_r($this->getIntegers(), true) . "<br/>");
}
}
$t = new JustTest();
$t->filledInteger();
?>
The result is:
Before change
Array ( [0] => 1 [1] => 10 )
After change
Array ( [0] => 2 [1] => 20 )
Values of n & x
2
20
call getIntegers again
Array ( [0] => 2 [1] => 20 )
That is what I exactly need. Im just curious how do I implement this in java
Hope you understood.
Next example:
public abstract class ParentTest {
abstract int[] getIntegers();
public void fillIntegers(int[] newIntegers) {
int[] integersOfChild = getIntegers();
for (int i = 0; i < integersOfChild.length; i++) {
integersOfChild[i] = newIntegers[i];
}
}
}
public class ChildTest extends ParentTest {
private int x;
private int y;
#Override
int[] getIntegers() {
return new int[] {x, y};
}
}
public class UseTest {
void main() {
List<ParentTest> list;
for (ParentTest item : list) {
item.fillIntegers(myItegers);
}
}
}
This is what I need. I have a list of ParentTest instances (it may be ChildTest, or ChildTest2, or ChildTest3; but they all children of a ParentTest) and I need to fill all fields with my integer values, but I dont know if items in the list instances of a ChildTest, or ChildTest2, or ChildTest3 class
How do I implement this in Java?
With great pain via the Reflection API. If you want to write code like this, the best idea is to use another language.
Consider programming in Groovy instead. You can use array syntax to directly access class members by name: t["n"] = 2; This works with legacy Java code, so there is no need to modify TestClass to support this usage.
The concept you are talking about is called pass by reference. Java has for the most part abandoned it - it creates too many side-effects, like the one you are seeing here.
The issue is that while unfortunately you can't do this here, it actually prevents a huge number of unintentional bugs being released.
What about something like that:
public final class JustTest {
private final Map<String, Object> fields;
public void filledInteger() {
System.out.println("Before change\n" + this.fields);
fields.put("N", 2);
fields.put("X", 20);
System.out.println("After change\n" + this.fields);
System.out.println("Values of name & xml\n" + fields.get("N")
+ "\n" + fields.get("X"));
}
private JustTest() {
this.fields = Maps.newHashMap(); // guava
fields.put("N", 1);
fields.put("X", 10);
}
public static void main(String[] args) {
final JustTest t = new JustTest();
t.filledInteger();
}
}
You can't do individual fields without reflection, but you can change the contents of collections. Note that this is not really intended behavior, but rather something you have to be careful of when using collections.
This outputs 5 3 2 4 2 4
public class Test
{
public Vector<Integer> args = new Vector<Integer>();
public void fillArgs()
{
args.add(5);
args.add(3);
}
public Vector<Integer> getArgs()
{
return args;
}
public static void main(String args[])
{
Test s = new Test();
s.fillArgs();
Vector<Integer> temp = s.getArgs();
for (Integer i : temp)
System.out.println(i);
temp.setElementAt(2, 0);
temp.setElementAt(4, 1);
for (Integer i : temp)
System.out.println(i);
for (Integer i : s.getArgs())
System.out.println(i);
}
}
Your php example does not return an array of ints, but rather an array of int pointers. This is NOT something you can do in Java, in fact, this is NOT something you want to do in Java. Give a use case, and there is likely a better way to solve the problem you have.
If you want to return an object that others can affect and that are contained as member variables, do that. An ArrayList, HashMap, etc... there are plenty of things that can fit your needs. If you are given someone elses class and you must stick your nose in their code, you can get around their private declaration doing the following:
public void setN(JustTest j, int n) {
//You would handle some exceptions here also
Field f = JustTest.class.getDeclaredField("n");
f.setInt(j, n);
}
I am in the process of refactoring my existing code. It actually works fine, but it is a bit cluttered with multiple if-else conditionals checking the value of one variable and change the value of a second variable to an updated value taken from a fixed enumeration structure.
else if (var1 == 'valueX')
{
if (var2 == MyEnum.A)
var2 = MyEnum.B;
else if (var2 == MyEnum.B)
var2 = MyEnum.C;
else if (var2 == MyEnum.C)
var2 = MyEnum.D;
else if (var2 == MyEnum.D)
var2 = MyEnum.A;
}
else if (....)
{
..similar block of conditionals
}
I am a bit confused as to what is the best way to refactor and clean-up this code. Would you suggest the use of a switch perhaps? Or something more elegant?
Thanks in advance!
The classic answer to refactoring conditionals is Replace Conditional With Polymorphism. In this case, if each of MyEnum knew what its successor was, you could simply say (in the 'valuex' case: var2 = var2.successor. For var1 - if it could be an object that implemented an interface that knew how to handle whatever you're doing inside the loop, and each implementing class knew what it, specifically, should do... Well, you'd be done.
Update:
And here's a dandy little successor function in a test case:
public class EnumTest extends TestCase {
private enum X {
A, B, C;
public X successor() {
return values()[(ordinal() + 1) % values().length];
}
};
public void testSuccessor() throws Exception {
assertEquals(X.B, X.A.successor());
assertEquals(X.C, X.B.successor());
assertEquals(X.A, X.C.successor());
}
}
At least with J2SE 1.5 forward, you can give enums extra attributes. This means you might be able to replace that entire string of if-else with something that looks like
var2 = var1.getNextInSequence();
Now, in this case, it looks like you would want the attribute to be a reference to another enum, which adds some wrinkles, for example you can't forward reference enums when you initialize them, but there might be a workable solution for you this way.
When the attributes aren't other instances of the same enum, this kind of thing will work:
public enum Animal {
FOX(4),
CHICKEN(2),
WORM(0);
private int countLegs;
Animal(int n) {
countLegs = n;
}
public int getLegCount() {
return countLegs;
}
// .. more getters setters etc
}
But when the enum is self-referential, you have to be careful about the order of declaration of your instances. I.e., this will have some issues:
public enum Animal {
FOX(4, CHICKEN), // 'CHICKEN' doesn't exist yet
WORM(0, null),
CHICKEN(2, WORM); // this actually will compile
private int countLegs;
private Animal eatsWhat;
Animal(int n, Animal dinner) {
countLegs = n;
eatsWhat = dinner;
}
public int getLegCount() {
return countLegs;
}
// .. getters, setters, etc
}
So if you had need of a circular set of references among the enums, you'd have to work something else out, but if not, you could use this technique, though you may have to order your enum instances just so to make it work.
You can use a simple map:
enum MyEnum { A, B, C };
Map<MyEnum, MyEnum> VALUE_X = new HashMap<MyEnum, MyEnum>() {{
put(MyEnum.A, MyEnum.B);
put(MyEnum.B, MyEnum.C);
...
}};
// define another kind of ordering
Map<MyEnum, MyEnum> VALUE_Y = new HashMap<MyEnum, MyEnum>() {{
put(MyEnum.A, MyEnum.D);
put(MyEnum.B, MyEnum.A);
...
}};
This way, the logic of the next var2 value isn't hard-coded in the enum itself, and can be dependant of context (i.e. value of var1):
if ("valueX".equals(var1)) { // use equals() instead of == for Strings
var2 = VALUE_X.get(var2);
}
else if ("valueY".equals(var1)) {
var2 = VALUE_Y.get(var2);
}
I've the enum type ReportTypeEnum that get passed between methods in all my classes but I then need to pass this on the URL so I use the ordinal method to get the int value. After I get it in my other JSP page, I need to convert it to back to an ReportTypeEnum so that I can continue passing it.
How can I convert ordinal to the ReportTypeEnum?
Using Java 6 SE.
To convert an ordinal into its enum representation you might want to do this:
ReportTypeEnum value = ReportTypeEnum.values()[ordinal];
Please notice the array bounds.
Note that every call to values() returns a newly cloned array which might impact performance in a negative way. You may want to cache the array if it's going to be called often.
Code example on how to cache values().
This answer was edited to include the feedback given inside the comments
This is almost certainly a bad idea. Certainly if the ordinal is de-facto persisted (e.g. because someone has bookmarked the URL) - it means that you must always preserve the enum ordering in future, which may not be obvious to code maintainers down the line.
Why not encode the enum using myEnumValue.name() (and decode via ReportTypeEnum.valueOf(s)) instead?
If I'm going to be using values() a lot:
enum Suit {
Hearts, Diamonds, Spades, Clubs;
public static final Suit values[] = values();
}
Meanwhile wherever.java:
Suit suit = Suit.values[ordinal];
If you want the array to be private, be my guest:
private static final Suit values[] = values();
public static Suit get(int ordinal) { return values[ordinal]; }
...
Suit suit = Suit.get(ordinal);
Mind your array bounds.
I agree with most people that using ordinal is probably a bad idea. I usually solve this problem by giving the enum a private constructor that can take for example a DB value then create a static fromDbValue function similar to the one in Jan's answer.
public enum ReportTypeEnum {
R1(1),
R2(2),
R3(3),
R4(4),
R5(5),
R6(6),
R7(7),
R8(8);
private static Logger log = LoggerFactory.getLogger(ReportEnumType.class);
private static Map<Integer, ReportTypeEnum> lookup;
private Integer dbValue;
private ReportTypeEnum(Integer dbValue) {
this.dbValue = dbValue;
}
static {
try {
ReportTypeEnum[] vals = ReportTypeEnum.values();
lookup = new HashMap<Integer, ReportTypeEnum>(vals.length);
for (ReportTypeEnum rpt: vals)
lookup.put(rpt.getDbValue(), rpt);
}
catch (Exception e) {
// Careful, if any exception is thrown out of a static block, the class
// won't be initialized
log.error("Unexpected exception initializing " + ReportTypeEnum.class, e);
}
}
public static ReportTypeEnum fromDbValue(Integer dbValue) {
return lookup.get(dbValue);
}
public Integer getDbValue() {
return this.dbValue;
}
}
Now you can change the order without changing the lookup and vice versa.
You could use a static lookup table:
public enum Suit {
spades, hearts, diamonds, clubs;
private static final Map<Integer, Suit> lookup = new HashMap<Integer, Suit>();
static {
int ordinal = 0;
for (Suit suit : EnumSet.allOf(Suit.class)) {
lookup.put(ordinal, suit);
ordinal+= 1;
}
}
public Suit fromOrdinal(int ordinal) {
return lookup.get(ordinal);
}
}
This is what I use. I make no pretense that it's far less "efficient" than the simpler solutions above. What it does do is provide a much clearer exception message than "ArrayIndexOutOfBounds" when an invalid ordinal value is used in the solution above.
It utilizes the fact that EnumSet javadoc specifies the iterator returns elements in their natural order. There's an assert if that's not correct.
The JUnit4 Test demonstrates how it's used.
/**
* convert ordinal to Enum
* #param clzz may not be null
* #param ordinal
* #return e with e.ordinal( ) == ordinal
* #throws IllegalArgumentException if ordinal out of range
*/
public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) {
EnumSet<E> set = EnumSet.allOf(clzz);
if (ordinal < set.size()) {
Iterator<E> iter = set.iterator();
for (int i = 0; i < ordinal; i++) {
iter.next();
}
E rval = iter.next();
assert(rval.ordinal() == ordinal);
return rval;
}
throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size());
}
#Test
public void lookupTest( ) {
java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3);
System.out.println(tu);
}
Safety first (with Kotlin):
// Default to null
EnumName.values().getOrNull(ordinal)
// Default to a value
EnumName.values().getOrElse(ordinal) { EnumName.MyValue }
This is what I do on Android with Proguard:
public enum SomeStatus {
UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order
private static SomeStatus[] values = null;
public static SomeStatus fromInteger(int i) {
if(SomeStatus.values == null) {
SomeStatus.values = SomeStatus.values();
}
if (i < 0) return SomeStatus.values[0];
if (i >= SomeStatus.values.length) return SomeStatus.values[0];
return SomeStatus.values[i];
}
}
it's short and I don't need to worry about having an exception in Proguard
You can define a simple method like:
public enum Alphabet{
A,B,C,D;
public static Alphabet get(int index){
return Alphabet.values()[index];
}
}
And use it like:
System.out.println(Alphabet.get(2));
public enum Suit implements java.io.Serializable, Comparable<Suit>{
spades, hearts, diamonds, clubs;
private static final Suit [] lookup = Suit.values();
public Suit fromOrdinal(int ordinal) {
if(ordinal< 1 || ordinal> 3) return null;
return lookup[value-1];
}
}
the test class
public class MainTest {
public static void main(String[] args) {
Suit d3 = Suit.diamonds;
Suit d3Test = Suit.fromOrdinal(2);
if(d3.equals(d3Test)){
System.out.println("Susses");
}else System.out.println("Fails");
}
}
I appreciate that you share with us if you have a more efficient code, My enum is huge and constantly called thousands of times.
So one way is to doExampleEnum valueOfOrdinal = ExampleEnum.values()[ordinal]; which works and its easy, however,
as mentioned before, ExampleEnum.values() returns a new cloned array for every call. That can be unnecessarily expensive. We can solve that by caching the array like so ExampleEnum[] values = values(). It is also "dangerous" to allow our cached array to be modified. Someone could write ExampleEnum.values[0] = ExampleEnum.type2; So I would make it private with an accessor method that does not do extra copying.
private enum ExampleEnum{
type0, type1, type2, type3;
private static final ExampleEnum[] values = values();
public static ExampleEnum value(int ord) {
return values[ord];
}
}
You would use ExampleEnum.value(ordinal) to get the enum value associated with ordinal
There is an Easy and Bad way and there is a fairly easy and right way.
First, the easy and bad (those are usually very popular). Enum class method returns an array of all available instances via the values() method and you can access the enum object via array index.
RenderingMode mode = RenderingMode.values()[index];
//Enum Class somewhere else
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
}
//RenderingMode.values()[0] will return RenderingMode.PLAYING
//RenderingMode.values()[1] will return RenderingMode.PREVIEW
//Why this is bad? Because it is linked to order of declaration.
//If you later changed the order here, it will impact all your existing logic around this.
public enum RenderingMode
{
PREVIEW,
VIEW_SOLUTION,
PLAYING;
}
//Now
//RenderingMode.values()[0] will return RenderingMode.PREVIEW
//RenderingMode.values()[1] will return RenderingMode.VIEW_SOLUTION
Here is the right way to do it.
Create a static method fromInt in your enum class.
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
public static RenderingModefromInt(int index)
{
//this is independent of order of declaration
switch (index)
{
case 0: return PLAYING;
case 1: return PREVIEW;
case 2: return VIEW_SOLUTION;
}
//Consider throwing Exception here
return null;
}
}
public enum Status {
STATUS_1, STATUS_2, STATUS_3, STATUS_4;
public static Status getStatusByOrdinal(int ordinal) {
for (Status status : values()) {
if (status.ordinal() == ordinal) {
return status;
}
}
return STATUS_1;
}
}
In this way you can not depend on compile-time generics resolution(so having an enum class instance you can create whenever enum you want, even those types created with Class.forMame)
public Object getInstance(Class enumClazz, int ordinal) throws Exception {
Object[] allEnums = enumClazz.getDeclaredMethod("values", Object[].class).invoke(null, null);
return allEnums[ordinal];
}
Every enum has name(), which gives a string with the name of enum member.
Given enum Suit{Heart, Spade, Club, Diamond}, Suit.Heart.name() will give Heart.
Every enum has a valueOf() method, which takes an enum type and a string, to perform the reverse operation:
Enum.valueOf(Suit.class, "Heart") returns Suit.Heart.
Why anyone would use ordinals is beyond me. It may be nanoseconds faster, but it is not safe, if the enum members change, as another developer may not be aware some code is relying on ordinal values (especially in the JSP page cited in the question, network and database overhead completely dominates the time, not using an integer over a string).