I need to accomplish the following (this is a simplified version):
enum Animals{
enum Cats{tabby("some value"), siamese("some value")},
enum Dogs{poodle("some value"), dachsund("some value")},
enum Birds{canary("some value"), parrot("some value")}
private String someValue = "";
private ShopByCategory(String someValue)
{
this.someValue = someValue;
}
public String getSomeValue()
{
return this.someValue;
}
}
So that I can access these items as follows:
string cat1 = Animals.Cats.tabby.getSomeValue;
string dog1 = Animals.Dogs.dachsund.getSomeValue;
string bird1 = Animals.Birds.canary.getSomeValue;
The reason why I am attempting to do this with enums is the fact that I need to be able to access each tier without having to a) instantiate a class, b) hide the names of the tiers behind a method name, or c) use an iterator to go through an EnumSet.
Is this at all possible? What would you suggest instead of enums?
//Animals.java
public class Animals {
public static class Cats {
public static final String tabby = "some value";
public static final String siamese = "some value";
}
public static class Dogs {
public static final String poodle = "some value";
public static final String dachsund = "some value";
}
public static class Birds {
public static final String canary = "some value";
public static final String parrot = "some value";
}
}
//ShopByCategory.java
public class ShopByCategory {
private String someValue;
public ShopByCategory(String value){
this.someValue = value;
}
public String getSomeValue(){
return this.someValue;
}
}
//Main.java - an example of what you can do
public class Main {
public static void main(String[] args){
ShopByCategory sbc = new ShopByCategory(Animals.Birds.canary);
System.out.println(sbc.getSomeValue());
System.out.println(Animals.Dogs.poodle);
}
}
Here's how I finally ended up implementing my solution:
public static class Animals()
{
public enum Cats()
{
tabby("some value"),
siamese("some value");
private String someValue = "";
private ShopByCategory(String someValue)
{
this.someValue = someValue;
}
public String getSomeValue()
{
return this.someValue;
}
}
public enum Dogs()
{
poodle("some value"),
dachsund("some value");
private String someValue = "";
private ShopByCategory(String someValue)
{
this.someValue = someValue;
}
public String getSomeValue()
{
return this.someValue;
}
}
public enum Birds()
{
canary("some value"),
parrot("some value");
private String someValue = "";
private ShopByCategory(String someValue)
{
this.someValue = someValue;
}
public String getSomeValue()
{
return this.someValue;
}
}
This way, I don't have to instantiate the class or call any class specific methods to get my desired info. I can get at all the "some value" strings like this:
string cat1 = Animals.Cats.tabby.getSomeValue;
string dog1 = Animals.Dogs.dachsund.getSomeValue;
string bird1 = Animals.Birds.canary.getSomeValue;
Related
For example I have two simple as possible classes, A and B
I want to take some action on objects of B, if some specific field of A object is changed I should do one thing, If some other field is changed I should do second thing, how can I do that with Lambda?
A:
public class A {
private int someField;
private String nextField;
public A(int someField, String nextField) {
this.someField = someField;
this.nextField = nextField;
}
public int getSomeField() {
return someField;
}
public void setSomeField(int someField) {
this.someField = someField;
}
public String getNextField() {
return nextField;
}
public void setNextField(String nextField) {
this.nextField = nextField;
}
}
B:
public class B {
private String someField;
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public B(String someField) {
this.someField = someField;
}
}
Demo:
public class Demo {
public static <T> boolean isFieldChanged(T oldValue, T newValue) {
return !Objects.equals(oldValue, newValue);
}
public static void someActionOne(B test){
return;
}
public static void someActionTwo(B test){
return;
}
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
Consumer<B> action = null;
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
action = Demo::someActionOne;
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
action = Demo::someActionTwo;
}
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
mockData.forEach(b -> action.accept(b));
}
}
How can I avoid compile error in that case?
To be effectively-final, a variable must not be changed after initialization.
If you want to use different actions, just initialize them twice:
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
mockData.forEach(Demo::someActionOne);
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
mockData.forEach(Demo::someActionTwo);
}
}
I have a Class A with name and value attributes.
public class A {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I have another Class B, such as
public class B {
private String attribute01;
private String attribute01;
private String attribute01;
public String getAttribute01() {
return attribute01;
}
public void setAttribute01(String name) {
this.attribute01 = name;
}
...
}
I would like to return a list with A type, having attribute01 key and where value is getAttribute01() from B, such as ({attribute01, getAttribute01()},{attribute02, getAttribute02()}).
How to implement it?.
Thanks in advance.
Actually I can use a very stupid way, such as
public List<A> keyvalueList(final B objB) {
List<A> list = new ArrayList<>();
A objA = new A();
objA.setName("attribute01");
objA.setValue(objB.getAttribute01());
list.add(objA);
objA = new A();
objA.setName("attribute02");
objA.setValue(objB.getAttribute02());
list.add(objA);
...
return list;
}
Part of them hard coding, obvious it is not a smart way, any proposal.
I wrote sample code for List.Please check my code that is ok to use or not.I added another extra class C.in C,it has two attribute String nameFromA and String attFromB.You should add this C object to list.Following is sample code.
public class A {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class B {
private String att1;
private String att2;
private String att3;
public String getAtt1() {
return att1;
}
public void setAtt1(String att1) {
this.att1 = att1;
}
public String getAtt2() {
return att2;
}
public void setAtt2(String att2) {
this.att2 = att2;
}
public String getAtt3() {
return att3;
}
public void setAtt3(String att3) {
this.att3 = att3;
}
}
public class C {
private String namefromA;
private String attfromB;
public String getNamefromA() {
return namefromA;
}
public void setNamefromA(String namefromA) {
this.namefromA = namefromA;
}
public String getAttfromB() {
return attfromB;
}
public void setAttfromB(String attfromB) {
this.attfromB = attfromB;
}
}
public class Test {
public static void main(String args[]){
C c = new C();
A a = new A();
B b = new B();
a.setName("A1");
b.setAtt1("100");
c.setNamefromA(a.getName());
c.setAttfromB(b.getAtt1());
List list = new ArrayList();
//use generic
list.add(c);
}
}
if you don't want to use class C,then you can use Test class like that
import java.util.ArrayList;
import java.util.List;
public class Test {
private String nameFromA;
private String valueFromB;
public Test(String nameFromA, String valueFromB) {
super();
this.nameFromA = nameFromA;
this.valueFromB = valueFromB;
}
public static void main(String args[]){
A a = new A();
B b = new B();
a.setName("A1");
b.setAtt1("100");
Test test = new Test(a.getName(),b.getAtt1());
List list = new ArrayList();
list.add(test);
}
}
This is my opinion only.Please check it is ok or not.
Is an enum able to store references to a getter method, using a Supplier?
To be use like that :
String value = myEnum.getValue(object)
I can't figure how to write it without compiling errors.
If I get you right then you want to do something like this:
import java.util.function.DoubleSupplier;
public class Test {
enum MathConstants {
PI(Test::getPi), E(Test::getE);
private final DoubleSupplier supply;
private MathConstants(DoubleSupplier supply) {
this.supply = supply;
}
public double getValue() {
return supply.getAsDouble();
}
}
public static void main(String... args) {
System.out.println(MathConstants.PI.getValue());
}
public static double getPi() {
return Math.PI;
}
public static double getE() {
return Math.E;
}
}
It's not very difficult if the return type for all the getters is the same. Consider the following PoJo class:
public static class MyPoJo {
final String foo, bar;
public MyPoJo(String foo, String bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public int getBaz() {
return 5;
}
}
Then we may have such enum:
public static enum Getters {
FOO(MyPoJo::getFoo), BAR(MyPoJo::getBar);
private final Function<MyPoJo, String> fn;
private Getters(Function<MyPoJo, String> fn) {
this.fn = fn;
}
public String getValue(MyPoJo object) {
return fn.apply(object);
}
}
And use it like this:
System.out.println(Getters.FOO.getValue(new MyPoJo("fooValue", "barValue"))); // fooValue
However it would be problematic if you want to return different types. In this case I'd suggest to use normal class with predefined instances instead of enum:
public static final class Getters<T> {
public static final Getters<String> FOO = new Getters<>(MyPoJo::getFoo);
public static final Getters<String> BAR = new Getters<>(MyPoJo::getBar);
public static final Getters<Integer> BAZ = new Getters<>(MyPoJo::getBaz);
private final Function<MyPoJo, T> fn;
private Getters(Function<MyPoJo, T> fn) {
this.fn = fn;
}
public T getValue(MyPoJo object) {
return fn.apply(object);
}
}
Usage is the same:
System.out.println(Getters.FOO.getValue(new MyPoJo("fooValue", "barValue"))); // fooValue
System.out.println(Getters.BAZ.getValue(new MyPoJo("fooValue", "barValue"))); // 5
I'm facing this task:
I have class A and class B. These two classes are different but almost the same.
I need to somehow merge them into 1 Single array of objects so I will be able to use them later in a list that combines both classes.
Class A:
public class Followers {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
Class B:
public class Following {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
I've tried doing this next move:
Object[] obj1 = (Object[]) followers;
Object[] obj2 = (Object[]) followings;
Object[] completeArray = ArrayUtils.addAll(obj1, obj2);
Where followers and followings are both arrays of the corresponding classes. Then in my list adapter I use:
if (values[currentItem] instanceof Followers) { BLA BLA BLA}
else if (values[currentItem] instanceof Following) { BLA BLA BLA}
But I get this exception:
Caused by: java.lang.ArrayStoreException: source[0] of type json.objects.Following cannot be stored in destination array of type json.objects.Followers[]
What will be the best way to merge two arrays of different objects into one array?
Will just implementing the same interface between them do the job and then they will basically be in an array of the interface type?
what other ways do you recommend?
Try this
Object[] completeArray = new Object[0];
completeArray = ArrayUtils.addAll(completeArray, obj1);
completeArray = ArrayUtils.addAll(completeArray, obj2);
If you make both classes implement a common interface you can manipulate arrays/lists of them as if they contains instances of the interface.
public interface Follow {
public String getRequest_id();
public String getState();
}
public class Follower implements Follow {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
public class Following implements Follow {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
public void test() {
List<Follow> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Follow f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Alternatively you could put them in a hierarchy:
public class Entity {
private String request_id;
private String state;
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
}
public class Follower extends Entity {
private String number_sender;
public String getNumber_sender() {
return number_sender;
}
}
public class Following extends Entity {
private String name;
public String getName() {
return name;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Entity f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Or you could make the extra fields into attributes.
enum Attribute {
Follows,
Followed;
}
public static class Entity {
private String request_id;
private String state;
EnumMap<Attribute, String> attributes = new EnumMap<>(Attribute.class);
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
// Factory to make entities.
static Entity make(Attribute attribute, String value) {
Entity e = new Entity();
e.attributes.put(attribute, value);
return e;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(Entity.make(Attribute.Follows, "Fred"));
all.add(Entity.make(Attribute.Followed, "Gill"));
for (Entity f : all) {
String id = f.getRequest_id();
String state = f.getState();
}
}
There are an infinite number of possibilities.
USE concat
var combined= obj1.concat(obj2); // Merges both arrays
Try this.
private Object[] appendObj(Object[] obj, Object newObj) {
ArrayList<Object> temp = new ArrayList<Object>(Arrays.asList(obj));
temp.add(newObj);
return temp.toArray();
}
How can I get the name of a Java Enum type given its value?
I have the following code which works for a particular Enum type, can I make it more generic?
public enum Category {
APPLE("3"),
ORANGE("1"),
private final String identifier;
private Category(String identifier) {
this.identifier = identifier;
}
public String toString() {
return identifier;
}
public static String getEnumNameForValue(Object value){
Category[] values = Category.values();
String enumValue = null;
for(Category eachValue : values) {
enumValue = eachValue.toString();
if (enumValue.equalsIgnoreCase(value)) {
return eachValue.name();
}
}
return enumValue;
}
}
You should replace your getEnumNameForValue by a call to the name() method.
Try below code
public enum SalaryHeadMasterEnum {
BASIC_PAY("basic pay"),
MEDICAL_ALLOWANCE("Medical Allowance");
private String name;
private SalaryHeadMasterEnum(String stringVal) {
name=stringVal;
}
public String toString(){
return name;
}
public static String getEnumByString(String code){
for(SalaryHeadMasterEnum e : SalaryHeadMasterEnum.values()){
if(e.name.equals(code)) return e.name();
}
return null;
}
}
Now you can use below code to retrieve the Enum by Value
SalaryHeadMasterEnum.getEnumByString("Basic Pay")
Use Below code to get ENUM as String
SalaryHeadMasterEnum.BASIC_PAY.name()
Use below code to get string Value for enum
SalaryHeadMasterEnum.BASIC_PAY.toString()
Try, the following code..
#Override
public String toString() {
return this.name();
}
Here is the below code, it will return the Enum name from Enum value.
public enum Test {
PLUS("Plus One"), MINUS("MinusTwo"), TIMES("MultiplyByFour"), DIVIDE(
"DivideByZero");
private String operationName;
private Test(final String operationName) {
setOperationName(operationName);
}
public String getOperationName() {
return operationName;
}
public void setOperationName(final String operationName) {
this.operationName = operationName;
}
public static Test getOperationName(final String operationName) {
for (Test oprname : Test.values()) {
if (operationName.equals(oprname.toString())) {
return oprname;
}
}
return null;
}
#Override
public String toString() {
return operationName;
}
}
public class Main {
public static void main(String[] args) {
Test test = Test.getOperationName("Plus One");
switch (test) {
case PLUS:
System.out.println("Plus.....");
break;
case MINUS:
System.out.println("Minus.....");
break;
default:
System.out.println("Nothing..");
break;
}
}
}
In such cases, you can convert the values of enum to a List and stream through it.
Something like below examples. I would recommend using filter().
Using ForEach:
List<Category> category = Arrays.asList(Category.values());
category.stream().forEach(eachCategory -> {
if(eachCategory.toString().equals("3")){
String name = eachCategory.name();
}
});
Or, using Filter:
When you want to find with code:
List<Category> categoryList = Arrays.asList(Category.values());
Category category = categoryList.stream().filter(eachCategory -> eachCategory.toString().equals("3")).findAny().orElse(null);
System.out.println(category.toString() + " " + category.name());
When you want to find with name:
List<Category> categoryList = Arrays.asList(Category.values());
Category category = categoryList.stream().filter(eachCategory -> eachCategory.name().equals("Apple")).findAny().orElse(null);
System.out.println(category.toString() + " " + category.name());
Hope it helps! I know this is a very old post, but someone can get help.
I believe it's better to provide the required method in the enum itself. This is how I fetch Enum Name for a given value. This works for CONSTANT("value") type of enums.
public enum WalletType {
UPI("upi-paymode"),
PAYTM("paytm-paymode"),
GPAY("google-pay");
private String walletType;
WalletType(String walletType) {
this.walletType = walletType;
}
public String getWalletType() {
return walletTypeValue;
}
public WalletType getByValue(String value) {
return Arrays.stream(WalletType.values()).filter(wallet -> wallet.getWalletType().equalsIgnoreCase(value)).findFirst().get();
}
}
e.g. WalletType.getByValue("google-pay").name()
this will give you - GPAY
enum MyEnum {
ENUM_A("A"),
ENUM_B("B");
private String name;
private static final Map<String,MyEnum> unmodifiableMap;
MyEnum (String name) {
this.name = name;
}
public String getName() {
return this.name;
}
static {
Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
for (MyEnum instance : MyEnum.values()) {
map.put(instance.getName().toLowerCase(),instance);
}
unmodifiableMap = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return unmodifiableMap.get(name.toLowerCase());
}
}
Now you can use below code to retrieve the Enum by Value
MyEnum.get("A");