Java String contain method and enum - java

I have enum defined in class as
public enum EnumSample {
SPACE,
NASA,
SPUTNIK;
}
In class Test, I have a method with following code snippet
if (str.contains(<>)) {
Is it possible to search all enum values in contain method of String?

You can iterate over the .values() of the enum and apply .contains() for each of them.
For example:
for (EnumSample value : EnumSample.values()) {
if (str.contains(value.name()) {
//do your thing
}
}

One problem with contains is that it finds parts of words - for example, it would find "NASA" in "NASAL DECONGESTANTS". If you would like your comparison to be fast, and look for specific words, not parts of words, use regex search instead.
The regex for your example would look like this:
\b(SPACE|NASA|SPUTNIK)\b
You can construct and use it like this:
static Pattern allEnumVals;
static {
StringBuilder b = new StringBuilder("\\b(");
boolean first = true;
for (EnumSample e : EnumSample.values()) {
if (!first) {
b.append("|");
} else {
first = false;
}
b.append(e.name());
}
b.append(")\\b");
allEnumVals = Pattern.compile(b.toString());
}
static boolean check(String str) {
return allEnumVals.matcher(str).find();
}

Related

java comparison of two enums

Given the test code:
#Test
public void testEnumAreEqual() {
for (var someEnum : SomeEnum.values()) {
Assertions.assertTrue(EnumUtils.isValidEnum(OtherEnum.class, someEnum.name()));
}
for (var otherEnum : OtherEnum.values()) {
Assertions.assertTrue(EnumUtils.isValidEnum(SomeEnum.class, otherEnum.name()));
}
}
I want to check if two given enums are containing the same values.
Is there maybe a more elegant way to do this?
Build a set of the names:
Set<String> someEnumNames =
Arrays.stream(SomeEnum.values())
.map(Enum::name)
.collect(toSet());
Do the same for OtherEnum (consider extracting the above into a method).
Then:
assertEquals(someEnumNames, otherEnumNames);

Sonarqube: How to get the expression string when writing custom java rules?

The target class is:
class Example{
public void m(){
System.out.println("Hello" + 1);
}
}
I want to get the full string of MethodInvocation "System.out.println("Hello" + 1)" for some regex check. How to write?
public class Rule extends BaseTreeVisitor implements JavaFileScanner {
#Override
public void visitMethodInvocation(MethodInvocationTree tree) {
//get the string of MethodInvocation
//some regex check
super.visitMethodInvocation(tree);
}
}
I wrote some code inspection rules using eclipse jdt and idea psi whose expression tree node has these attributes. I wonder why sonar's just has first and last token instead.
Thanks!
An old question, but I have a solution.
This works for any sort of tree.
#Override
public void visitMethodInvocation(MethodInvocationTree tree) {
int firstLine = tree.firstToken().line();
int lastLine = tree.lastToken().line();
String rawText = getRelevantLines(firstLine, lastLine);
// do your thing here with rawText
}
private String getRelevantLines(int startLine, int endLine) {
StringBuilder builder = new StringBuilder();
context.getFileLines().subList(startLine, endLine).forEach(builder::append);
return builder.toString();
}
If you want to refine further, you can also use firstToken().column or perhaps use the method name in your regex.
If you want more lines/bigger scope, just use the parent of that tree tree.parent()
This will also handle cases where the expression/params/etc span multiple lines.
There might be a better way... but I don't know of any other way. May update if I figure out something better.

Find a string in list of lists

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);
}

Most efficient way to convert Enum values into comma seperated String

I have a java class in which I store an Enum.(shown at the bottom of this question) In this enum, I have a method named toCommaSeperatedString() who returns a comma separated String of the enums values. I am using a StringBuilder after reading some information on performance in this question here.
Is the way I am converting this enum's values into a commaSeperatedString the most efficient way of doing so, and if so, what would be the most efficient way to remove the extra comma at the last char of the String?
For example, my method returns 123, 456, however I would prefer 123, 456. If I wanted to return PROPERTY1, PROPERTY2 I could easily use Apache Commons library StringUtils.join(), however, I need to get one level lower by calling the getValue method when I am iterating through the String array.
public class TypeEnum {
public enum validTypes {
PROPERTY1("123"),
PROPERTY2("456");
private String value;
validTypes(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static boolean contains(String type) {
for (validTypes msgType : validTypes.values()) {
if (msgType.value.equals(type)) {
return true;
}
}
return false;
}
public static String toCommaSeperatedString() {
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for(validTypes msgType : validTypes.values()) {
commaSeperatedValidMsgTypes.append(msgType.getValue() + ", ");
}
return commaSeperatedValidMsgTypes.toString();
}
}
}
I wouldn't worry much about efficiency. It's simple enough to do this that it will be fast, provided you don't do it in a crazy way. If this is the most significant performance bottleneck in your code, I would be amazed.
I'd do it something like this:
return Arrays.stream(TypeEnum.values())
.map(t -> t.value)
.collect(Collectors.joining(','));
Cache it if you want; but that's probably not going to make a huge difference.
A common pattern for the trailing comma problem I see is something like
String[] values = {"A", "B", "C"};
boolean is_first = true;
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for(String value : values){
if(is_first){
is_first = false;
}
else{
commaSeperatedValidMsgTypes.append(',');
}
commaSeperatedValidMsgTypes.append(value);
}
System.out.println(commaSeperatedValidMsgTypes.toString());
which results in
A,B,C
Combining this with the answers about using a static block to initialize a static final field will probably give the best performance.
The most efficient code is code that doesn't run. This answer can't ever change, so run that code as you have it once when creating the enums. Take the hit once, return the calculated answer every other time somebody asks for it. The savings in doing that would be far greater in the long term over worrying about how specifically to construct the string, so use whatever is clearest to you (write code for humans to read).
For example:
public enum ValidTypes {
PROPERTY1("123"),
PROPERTY2("345");
private final static String asString = calculateString();
private final String value;
private static String calculateString() {
return // Do your work here.
}
ValidTypes(final String value) {
this.value = value;
}
public static String toCommaSeparatedString() {
return asString;
}
}
If you have to call this static method thousand and thousand of times on a short period, you may worry about performance and you should first check that this has a performance cost.
The JVM performs at runtime many optimizations.
So finally you could write more complex code without added value.
Anyway, the actual thing that you should do is storing the String returned by toCommaSeperatedString and returned the same instance.
Enum are constant values. So caching them is not a problem.
You could use a static initializer that values a static String field.
About the , character, just remove it after the loop.
public enum validTypes {
PROPERTY1("123"), PROPERTY2("456");
private static String valueSeparatedByComma;
static {
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for (validTypes msgType : validTypes.values()) {
commaSeperatedValidMsgTypes.append(msgType.getValue());
commaSeperatedValidMsgTypes.append(",");
}
commaSeperatedValidMsgTypes.deleteCharAt
(commaSeperatedValidMsgTypes.length()-1);
valueSeparatedByComma = commaSeperatedValidMsgTypes.toString();
}
public static String getvalueSeparatedByComma() {
return valueSeparatedByComma;
}
I usually add a static method on the enum class itself:
public enum Animal {
CAT, DOG, LION;
public static String possibleValues() {
return Arrays.stream(Animal.values())
.map(Enum::toString)
.collect(Collectors.joining(","));
}
}
So I can use it like String possibleValues = Animal.possibleValues();

How to remove if else condition from loop?

I have a code snippet similar to the one below,
public ArrayList getReport(reportJDOList,accountType)
{
String abc = "";
for(ReportJDO reportJDO : reportJDOList)
{
if(accountType.equals("something")
abc = reportJDO.getThis();
else
abc = reportJDO.getThat();
//somecode goes here
}
returning List;
}
As I know the value of accountType before the iteration, I dont want this check to happen, for every entry in a list as it would cause numerous number of checks if the size of reportJDOList is 10000 for an instance. How we remove this thing from happening? Thanks in Advance :)
You can indeed peform check once and implement 2 loops:
if(accountType.equals("something") {
for(ReportJDO reportJDO : reportJDOList) {
abc = reportJDO.getThis();
}
} else {
for(ReportJDO reportJDO : reportJDOList) {
abc = reportJDO.getThat();
}
}
Obviously you can improve your design by either
separating you loops into 2 different methods
Using command pattern, i.e. implementing loop body in different command and executing it to loop.
Using Guava's Function (it is just improvement of #2)
Using java 8 streams.
IF you want to save the String comparison, make it once before the loop and store the result in a boolean variable :
String abc = "";
boolean isThis = accountType.equals("something");
for(ReportJDO reportJDO : reportJDOList) {
abc = isThis ? reportJDO.getThis() : reportJDO.getThat();
//somecode goes here
}
I'd vote for clean coding this - perform the check once and delegate the logic into private methods, each performing the loop individually. This duplicates code for the loop but gives greatest flexibility if at some point you need to do something more in SomethingReport that's not duplicated in OtherReport.
public ArrayList getReport(reportJDOList,accountType) {
if("soemthing".equals(accountType)) {
return getSomethingReport(reportJDOList);
} else {
return getOtherReport(reportJDOList);
}
}
private ArrayList getSomethingReport(reportJDOList) {
[...]
}
interface AccountHandler {
String get(Report r);
}
AccountHandler thisHandler= new AccountHandler() {
#Override
public String get(Report r) {
return r.getThis();
}
};
AccountHandler thatHandler= new AccountHandler() {
#Override
public String get(Report r) {
return r.getThat();
}
};
//...............
AccountHandler ah;
ah = (what.equalsIgnoreCase("this")) ? thisHandler : thatHandler;
Report r=new Report();
// loop
ah.get(r);
//Using reflection:
Report r = new Report();
Method thisMethod = r.getClass().getDeclaredMethod("getThis");
Method thatMethod = r.getClass().getDeclaredMethod("getThat");
Method m = (what.equalsIgnoreCase("this")) ? thisMethod : thatMethod;
m.invoke(r);

Categories