I have rs.getArray("lang"); which is java.sql.Array and the lang field is character varying[]. I want to convert it to List<MyEnumLanguage>. As an example I have {fr_FR,en_US} and I have used the following code to convert that my IDE didn't show any errors
List<MyEnumLanguage> myEnumLanguageList = (List<MyEnumLanguage>) rs.getArray("lang");
but it throws an exception org.postgresql.jdbc.PgArray cannot be cast to java.util.List.
My MyEnumLanguage is like:
public enum MyEnumLanguage {
en_US {
public String getCode() { return "en_US" }
},
de_DE {
public String getCode() { return "de_DE" }
};
private MyEnumLanguage() {
}
}
You cannot cast an array to List. Your IDE does not show any arror because casting happens on runtime.
Instead, you should use Arrays.asList(array) method, which returns a list containing all the elements of the array.
Note that if you want to map the elements of the array to another type, you could easily do that with streams. Example:
List<MyEnumLanguage> myEnumLanguageList = Arrays.asList(rs.getArray("lang"))
.stream()
.map(arrayElement -> convertToMyEnumLanguage(arrayElement))
.collect(Collectors.toList());
where convertToMyEnumLanguage() takes an element of your array and returns the corresponding MyEnumLanguage.
Take a look at this post: https://stackify.com/streams-guide-java-8/
UPDATE
Initially I missread the question. You have to first convert your PgArray to a normal java array, before you can use it in Arrays.asList().
This can be done using PgArray.getArray() method, and then cast the returned object to an array of the pgArray's containing type.
UPDATE 2
Improved example:
First of all you should define your enum like this:
public enum MyEnumLanguage {
en_US("en_US"),
de_DE("de_DE");
private final String code;
private MyEnumLanguage(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static MyEnumLanguage getEnumByCode(String code) {
if(code == null || code.isEmpty()) {
return null;
}
for(MyEnumLanguage e : values()) {
if(e.getCode().equals(code)) {
return e;
}
}
return null;
}
}
Then to map your pgArray to a List:
Array pgArray = rs.getArray("lang");
String[] langJavaArray = (String[]) pgArray.getArray(); //this returns an Object, so we cast it to a String array
List<MyEnumLanguage> myEnumLanguageList =
Arrays.stream(langJavaArray)
.map(MyEnumLanguage::getEnumByCode)
.collect(Collectors.toList())
;
Please note that the mapping function does not check for nulls. So if a wrong codes are passed, your list will contain nulls. If this is not the desired result, you have to perform the appropriate checks and handle null cases in your map function.
Related
Lets say I have a class
public class Ttype{
private String type = "";
public Ttype(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
and I have arraylist of this class
ArrayList<Ttype> type = new ArrayList<Ttype>();
I have added some elements to the arraylist
type.add( new new Ttype("Hello"));
type.add( new new Ttype("Bye"));
type.add( new new Ttype("Hi"));
I want to be able to return a string when I search for specefic string in the arraylist. What I mean by that is:
Ttype t = type.get("Hello"); //t will be set to "hello" if hello is in the arraylist.
How can I do that?
type.stream()
.filter(c -> c.getType().equals("test"))
.collect(Collectors.toList());
Well as others suggested in comments this will be much easy when you use a Map rather than ArrayList. But in your case to achieve what you need you can follow the below steps.This will be much easy when you use streams in Java 8.But I will provide a simple solution which you can achieve without streams.
Ttype result = null;//To store if an object found
String searchTxt = "Hello";
for(Ttype temp:type){//Iterating through the list find a match
if(temp.type.equlas(searchTxt)){
result = temp;
}
}
Now based on the value which contains in the result you can continue your work.If result is null after the iteration it means there is no matching item found.
Im new to java and have a list of objects named listAnimal, here's a sample below:
[Animal{name='Atlantic', type='Actinopterygii', scienName='sturio', country='Global', endangerment='Critical Endangerment', popTrend='Decreasing'}, Animal{name='eel', type='Actinopterygii', scienName='Anguilla anguilla', country='Europe', endangerment='Critical Endangerment', popTrend='Decreasing'},
i have some enums classes that i would like to use
public enum LevelOfEndangerment {
/**
* an enum to give values to levels of endangerment
*/
EXTINCT(8), NEAR_EXTINCT(7), CRITICAL_ENDANGERMENT(6), ENDANGERED(5), SOMEWHAT_VULNERABLE(4), NEAR_VULNERABLE(3),
NON_CONCERN(2), DATA_DEFICIENT(1), NOT_EVALUATED(0);
private int value;
LevelOfVulnerability (int aValue) {
this.value = aValue;
}
public int getValue () {
return value;
}
Im struggling to think of ways to loop through listAnimal and check the endangerment value in the Animal object details for example "Critical Endangerment" and use the enum to return the value 6 in accordance with its aValue.
Many Thanks
If you have single Animal then you can convert endangerment string into ENUM and get the value
String eng = animal.getEndargement();
LevelOfEndangerment engVal = LevelOfEndangerment.valueOf(eng.replace(" ","_").toUpperCase());
Integer value = engVal.getValue();
If you have list of Animal you can stream and get the value
List<Integer> values = listAnimal.stream()
.map(an-> LevelOfEndangerment.valueOf(an.getEndargement().replace(" ","_").toUpperCase())
.map(LevelOfEndangerment::getValue)
.collect(Collectors.toList());
I want to implement storing of enabled or disabled features into database row. When some String value is received from them the network I would like to compare it into ENUM.
ENUM:
public enum TerminalConfigurationFeatureBitString {
Authorize("authorize", 0), // index 0 in bit string
Authorize3d("authorize3d", 1), // index 1 in bit String
Sale("sale", 2), // index 2 in bit String
Sale3d("sale3d", 3), // index 3 in bit String
}
Map<TerminalConfigurationFeatureBitString, Boolean> featureMaps =
config.initFromDatabaseValue(optsFromDatabase);
featureMaps.get(transaction.transactionType);
The best way is to use featureMaps.get(TerminalConfigurationFeatureBitString.Sale);
But I don't know the incoming string what would be.
Now I get warning Unlikely argument type String for get(Object) on a Map<TerminalConfigurationFeatureBitString,Boolean>
Is there any other way to make a query into the ENUM without knowing the key?
In cases like these, I often find myself adding a static method getByX which does a lookup based upon a property of the enum:
public enum BitString {
//...
public static Optional<BitString> getByTransactionType(String transactionType)
{
return Arrays.stream(values())
.filter(x -> x.transactionType.equals(transactionType))
.findFirst();
}
}
Usage:
enum TransactionStatus
{
ENABLED, NOT_ENABLED, NOT_SUPPORTED
}
TransactionStatus status = BitString.getBygetByTransactionType(transaction.transactionType)
.map(bitString -> featureMaps.get(bitString))
.map(enabled -> enabled ? TransactionStatus.ENABLED : TransactionStatus.NOT_ENABLED)
.orElse(TransactionStatus.NOT_SUPPORTED);
Similar to #Michael's answer, you can just generate a static lookup map inside your enum which maps an enums transaction type to the actual enum:
private static final Map<String, TerminalConfigurationFeatureBitString> TRANSACTION_TYPE_TO_ENUM =
Arrays.stream(values()).collect(Collectors.toMap(
TerminalConfigurationFeatureBitString::getTransactionType,
Function.identity()
);
And then have a lookup method, also inside the enum:
public static TerminalConfigurationFeatureBitString getByTransactionType(String transactionType) {
TerminalConfigurationFeatureBitString bitString = TRANSACTION_TYPE_TO_ENUM.get(transactionType);
if(bitString == null) throw new NoSuchElementException(transactionType);
return bitString;
}
This in a way more performant than the mentioned answer, because the Map is created the first time the enum is loaded (So when it is the first time referenced). And thus the iteration happens only once. Also Maps have a rather fast lookup time so you could say that getting an enum this way works O(1) (when ignoring the initial computation time of O(n))
You can extend your enum with extra static method which will try to convert given String on enum item:
enum TerminalConfigurationFeatureBitString {
Authorize("authorize", 0), // index 0 in bit string
Authorize3d("authorize3d", 1), // index 1 in bit String
Sale("sale", 2), // index 2 in bit String
Sale3d("sale3d", 3); // index 3 in bit String
private final String value;
private final int index;
TerminalConfigurationFeatureBitString(String value, int index) {
this.value = value;
this.index = index;
}
public String getValue() {
return value;
}
public int getIndex() {
return index;
}
public static Optional<TerminalConfigurationFeatureBitString> fromValue(String value) {
for (TerminalConfigurationFeatureBitString item : values()) {
if (item.value.equals(value)) {
return Optional.of(item);
}
}
return Optional.empty();
}
}
In case option is not found, return Optional.empty(). If feature is not present it means String representation does not represent any feature. Usage:
public void test() {
EnumMap<TerminalConfigurationFeatureBitString, Boolean> featureMaps = new EnumMap<>(
TerminalConfigurationFeatureBitString.class);
Optional<TerminalConfigurationFeatureBitString> feature = TerminalConfigurationFeatureBitString.fromValue("authorize");
if (!feature.isPresent()) {
System.out.println("Feature is not foudn!");
} else {
Boolean authorize = featureMaps.get(feature.get());
if (authorize != null && authorize) {
System.out.println("Feature is enabled!");
} else {
System.out.println("Feature is disabled!");
}
}
}
Hey if anyone has an idea I would be really thankfull.
I'm in a Java stream and i would like to sort my list that i'll be returning.
I need to sort the list via TradPrefis ( MyObject::getTradPrefix ).
But this would be way too easy. Because i want to sort following the number at the end of TradPrefix exampleTradPrefix_[NUMBER TO SORT]
Exemple : hello_1
test_2
...
still_there_22
Here is a piece of code so you can imagine easier.
public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
return (toReturn.stream()
.map(this::createWsQuestion)
.sorted(comparing(WsQuestion::getTradPrefix.toString().length()))
.collect(Collectors.toCollection(LinkedHashSet::new)));
}
One method would simply be to split getTradPrefix().toString() by _ and parse the rightmost value as an int, and use it to sort the Stream:
public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
return toReturn.stream()
.map(this::createWsQuestion)
.sorted(Comparator.comparingInt(question -> {
String[] args = question.getTradPrefix().toString().split("_");
return Integer.parseInt(args[args.length - 1]);
}))
.collect(Collectors.toCollection(LinkedHashSet::new));
}
If I where you I would simply put a method on the WsQuestion class, let's call it sort order:
public int getSortOrder() {
return Integer.valueOf(tradPrefix.substring(tradPrefix.lastIndexOf("_") + 1));
}
The Integer parse is needed since comparing strings would give "11" < "2" (thanks Holger for pointing this out). The lastIndexOf() makes sure that any number of underscores are allowed in tradPrefix, as long as there is at least one.
Then simply create a comparotor by using Comparator.comparingInt()
public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
return (toReturn.stream()
.map(this::createWsQuestion)
.sorted(comparingInt(WsQuestion::getSortOrder))
.collect(Collectors.toCollection(LinkedHashSet::new)));
}
You can make a small Comparator like this:
private static final Comparator<String> questionComparator = Comparator.comparingInt(s -> {
String[] pieces = s.split("_");
return Integer.parseInt(pieces[pieces.length-1]);
});
Then use it in your sorted().
Having a separate Comparator will make your code more readable too, since you will be separating concerns.
return toReturn.stream()
.map(this::createWsQuestion)
.sorted(questionComparator)
.collect(Collectors.toCollection(LinkedHashSet::new));
I have more than 15 lists of strings, each list contains several different codes. Each list contains codes of one specific type.
I have one input code and have to find out which list that input code belongs to and return one specific String based on the result. I have used if, else if to do that. Below is sample code
private static String getCodeType(String inputCode) {
if (MyClass.getCodeTypeOneList().contains(inputCode)) {
return "CodeType_A";
} else if (MyClass.getCodeTypeTwoList().contains(inputCode)) {
return "CodeType_B";
} else if (MyClass.getCodeTypeThreeList().contains(inputCode)) {
return "CodeType_C";
} else if (MyClass.getCodeTypeFourList().contains(inputCode)) {
return "CodeType_D";
} else if (MyClass.getCodeTypeFiveList().contains(inputCode)) {
"CodeType_E;
} else if (MyClass.getCodeTypeixList().contains(inputCode)) {
return "CodeType_F";
} else if (MyClass.getWithDrawalCodeTypeList().contains(inputCode)) {
return "CodeType_G";
}
// similar 10 more if conditions
else {
return null;
}
}
Each List is like below:
public static List codeTypeOneList = new ArrayList();
public static final List<String> getCodeTypeOneList() {
codeTypeOneList.add("AFLS");
codeTypeOneList.add("EAFP");
codeTypeOneList.add("ZDTC");
codeTypeOneList.add("ZFTC");
codeTypeOneList.add("ATCO");
return codeTypeOneList;
}
(similar list for other code types)
is there any better way to achieve this? Thanks
As a one-time step, build a map:
Map<String, String> codeTypeMap = new HashMap<>();
for (String key : getCodeTypeOneList()) {
codeTypeMap.put(key, "CodeType_A");
}
for (String key : getCodeTypeTwoList()) {
codeTypeMap.put(key, "CodeType_B");
}
// ...
(You need to make sure either that no list element occurs in multiple lists; or to add them in order of reverse preference so that later code types overwrite earlier ones).
Then just use codeTypeMap.get to look up the type for the given code.
private static String getCodeType(String inputCode) {
return codeTypeMap.get(inputCode);
}