I'm trying to find an object in a list based on a set of criteria. The basic logic looks like this
for (objectx obj : list)
{
if (object.property1 > criteria1)
//accept object
else (object.property1 == criteria1)
{
if (object.property2 > criteria2)
//accept object
else (object.property2 == criteria2)
{
if (object.property3 > criteria3)
... etc
}
}
}
Is there an elegent way to simplify this mess?
boolean accept = false;
for (int i = 0; i < object.numProps(); i++) {
if (object.prop[i] > criteria[i]) {
accept = true;
break;
} else if (object.prop[i] < criteria[i])
break;
// loop continues only if object.prop[i] == criteria[i]
}
I would create a method that checks all of the properties then inside your loop you can simply say:
for (objectx obj : list)
{
if(checkProperties(obj))
{
//Do Stuff
}
}
Adding methods named after your business logic may help. Then reading the code should read like english and the actual comparisons are somewhere else. It makes it easier to think about too.
If you want to do something like I did before that can help. I wanted to search for objects in database with NHibernate like you did. I created Query object to collect every criteria entered by user . And When I set the related property on Query object I added this criteria like this.
public bool Archive
{
set
{
if(value)
{
criteria.Add(Restrictions.Eq("Archive", true));
}
}
}
public bool IsFavorite
{
set
{
if (value)
{
criteria.Add(Restrictions.Eq("IsFavorite", true));
}
}
}
If you just want to filter objects in memory. You can also use Specification Pattern.
Related
To summarize I am making a program for a metro ticket system. and I am using set and get methods for it, when it comes to boolean values (since I need to validate that the person enters enough money for the ticket) how am i supposed to put in the main class( it is defined in brain) using the set method and an if statement.Here is a little fraction of the entire code and the rest is on github(https://github.com/alexxei4/subwayticket). The main is basically the class that will be used for interaction with the user and the brain is where alot of the actions are defined.All help is appreciated, please and thank you.
if (Choice1a == 10){
if(subway1.ticketcounter1(true);){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1(false);){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
This is not how you evaluate boolean values, you just place the value in an if statement and it will proceed if true and refuse if false, also there is no need to duplicate the statement when you can just place an else block to handle situations that are not true:
if(subway1.ticketcounter1) {
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
Also do not include semicolons in if statements, that's incorrect syntax. Read more about how to use use boolean values here: https://codingbat.com/doc/java-if-boolean-logic.html
EDIT:
After reading through your Github code I see that ticketcounter1 indeed is a method, but what it's doing is trying to change the value of ticketcounter1 like it's a referenced object, but boolean are primitive data types and can't be referenced, and even if they could it still wouldn't work because Java is a pass-by-value language. Read here for more information on that.
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2){
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
Like the other answer said you should be returning the value as boolean instead of trying to change it:
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
But all in all your code demonstrated fundamental flaws in understanding how the language works, I would suggest picking up a good Java for beginners kind of book or do some introductory online tutorials. Here is a good place to start your learning journey: https://docs.oracle.com/javase/tutorial/java/index.html
You code is like this
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2) {
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
}
It should be like this. Instead of using the variable and passing it though parameter. Use getter. Besides that your code won't run since subway1.ticketcounter1(true) is giving nothing. It is only changing variables stored in Brain.java. No information is being sent to main.
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
You can create functions without parameters. I don't know what were you trying to do?
if (Choice1a == 10){
if(subway1.ticketcounter1()){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1()){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
subway1.ticketcounter1() will give either true and false. Do not use ; in if statement condition. ; ends the statement. Check this guide to learn about use of semi-colon If you do want to use ; The code should look like this
if (Choice1a == 10){
boolean ticketCounter1 = subway1.ticketcounter1();
if(ticketCounter1){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
} else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
P.S You don't need two ifs if-else would be better in this case
if(condition) {
// Conditions is true
} else {
// Condition is false
}
I have a small java class that will be run on a cloud application server, so it needs to execute as fast as possible.
What I need to do is iterate over a List<Map>, get the contents of the current Map and then do some logic on it. The Map contains strings and doubles.
This is my current implementation:
for (int i = 0; i < count; i++) {
Map data = result.get(i);
double priceToCheck = Double.parseDouble(data.get("value").toString());
String criteria = data.get("criteria").toString();
String coin = data.get("coin").toString();
if (coin.equals("BTC")) {
if (criteria.equals("above")) {
if (BTC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (BTC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("BCH")) {
if (criteria.equals("above")) {
if (BCH > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (BCH < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("ETH")) {
if (criteria.equals("above")) {
if (ETH > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (ETH < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("ETC")) {
if (criteria.equals("above")) {
if (ETC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (ETC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("LTC")) {
if (criteria.equals("above")) {
if (LTC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (LTC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("XRP")) {
if (criteria.equals("above")) {
if (XRP > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (XRP < priceToCheck) {
// create notification
sendNotification = true;
}
}
}
Where result is a List<Map>, "BTC" is a string and BTC is a double
As you can see the highest level if statements checks the string coin, there are six possible values. Once the coin is found I determine the value of criteria, and then do a comparison of doubles depending on the value of criteria
I feel as though this is a very cumbersome way of accomplishing this task, it works but its relatively slow. I can't think of a way to speed it up without directly accessing every Map element and manually checking the contents.
Does anyone else have any ideas?
I have a small java class that will be run on a cloud application server, so it needs to execute as fast as possible.
First of all, there there are some assumptions in there that is doubtful.
Yes, it is nice for your code to run as fast as possible, but in most cases it is not necessary. And in particular, the fact that you running on a cloud server does not necessarily make it essential.
You assume your application is not running fast enough. (Have you benchmarked it?)
You assume that this part of the code is (or will be) responsible for the code being too slow. (Have you implemented it? Have you profiled it?)
And this:
I feel as though this is a very cumbersome way of accomplishing this task, it works but its relatively slow.
Cumbersome and slow are not the same. Often cumbersome verbose / clunky is faster than concise / elegant.
So now to the potential performance issues with your code. (Bearing in mind that this could all be irrelevant of your assumptions are incorrect!)
If the fields are / can be known at compile time, is better to use a custom class than a Map. The Map::get method will be orders of magnitude slower than a getter on a custom class, and a Map will typically use an order of magnitude more memory.
A custom class will also allow you to use primitive types, etcetera instead of shoehorning the values into String. Avoiding that will have performance benefits too.
This is slow:
double priceToCheck = Double.parseDouble(data.get("value").toString());
You appear to be taking a double (or a Double), converting it to a string and then converting it back to adouble`. Conversions between numbers and decimal strings are relatively expensive.
If the values of coin and criteria are known at compile time, consider using an enum or boolean rather than a String. Comparison will be faster, and you will be able to use a switch statement ... or a simple if in the boolean case.
In fact, the iteration through the list is one aspect where this not a lot of opportunity to optimize.
There is one optimization that really stands out here. Your original code snippit will iterate through your entire list to adjust your sendNotification boolean.
If setting sendNotification all you need to do, you can strategically place break in each of your conditional. This will short-circuit the loop after the desired behavior. In the worst case scenario you would end up iterating through your entire list.
for (int i = 0; i < count; i++) {
if (coin.equals("BTC")) {
if (criteria.equals("above")) {
if (BTC > priceToCheck) {
// create notficaition
sendNotification = true;
break; // exits the loop
}
} else {
if (BTC < priceToCheck) {
// create notification
sendNotification = true;
break;
}
}
} else if (coin.equals("BCH")) {
if (criteria.equals("above")) {
if (BCH > priceToCheck) {
// create notficaition
sendNotification = true;
break;
}
I want to make the following code better, but cannot get a good idea.
Is there any way to solve this?
I just create a Android project and use greenDAO greendao to create tables by Class.
for (Field field : fields) {
fieldName = field.getName();
// we don't need this.
if ("serialVersionUID".equals(fieldName)) {
continue;
}
type = field.getType();
// primary key, just auto increment.
if ("id".equals(fieldName)) {
entity.addIdProperty().autoincrement();
continue;
}
// other fields
/*
* this is the problem what I want to solve.
* I thought it's too bad to read and have a bad looking.
*/
if (type.equals(String.class)) {
entity.addStringProperty(fieldName);
}else if (type.equals(Integer.class)) {
entity.addIntProperty(fieldName);
}else if (type.equals(Double.class)) {
entity.addDoubleProperty(fieldName);
}else if (type.equals(Float.class)) {
entity.addFloatProperty(fieldName);
}else if (type.equals(Long.class)) {
entity.addLongProperty(fieldName);
}else if (type.equals(Byte.class)) {
entity.addByteProperty(fieldName);
}else if (type.equals(Short.class)) {
entity.addShortProperty(fieldName);
}else if (type.equals(Boolean.class)) {
entity.addBooleanProperty(fieldName);
}else if (type.equals(Character.class)) {
entity.addStringProperty(fieldName);
}else if (type.equals(Date.class)) {
entity.addDateProperty(fieldName);
}
}
Java 8 solution: create a static Map of "adder methods" where each possible property type will be associated with corresponding lambda:
static final Map<Class<?>, BiConsumer<Entity, String>> ADDERS = new IdentityHashMap<>();
{{
ADDERS.put(String.class, Entity::addStringProperty);
ADDERS.put(Integer.class, Entity::addIntegerProperty);
//...
}}
then, for each field:
ADDERS.get(type).accept(entity, field.getName());
Class objects can be compared using == rather than .equals because there is only ever one instance per class.
It is occasionally necessary to have a sequence of nested if statements like this to find the right Class object, and this obviously very ugly (see the source code for Arrays.deepToString for a real example of this).
There are other solutions involving Map, or switching on type.getSimpleName(), however I would personally stick to the simple solution even if it is long-winded.
You could use more reflection.
String typeStr = type.getSimpleName();
switch(typeStr) {
case "Integer": typeStr = "Int"; break;
case "Character": typeStr = "String"; break;
}
Method m = enttity.getClass().getMethod("add" + typeStr + "Property", String.class);
m.invoke(entity, fieldname);
I was wondering whether its possible in java to evaluate multiple variables together in if-else condition like in python.
actual code
if(abc!=null && xyz!=null)
{//...}
dummy code
if(abc && xyz !=null)
{// will it be possible}
FIRST DRAFT
You can write smth like this:
boolean notNull(Object item) {
return item != null;
}
then you could use it like:
if (notNull(abc) && notNull(xyz)) {
//...
}
UPDATE 1:
I came up with a new idea, write function using varargs like:
boolean notNull(Object... args) {
for (Object arg : args) {
if (arg == null) {
return false;
}
}
return true;
}
usage: (you can pass to function multiple arguments)
if (notNull(abc, xyz)) {
//...
}
UPDATE 2:
The best approach is to use library apache commons ObjectUtils,
it contains several ready to use methods like:
allNotNull(Object... values),
anyNotNull(Object... values)
or firstNonNull(T... values)
the only way this would work is if abc was a boolean (and it wouldn't do what you're hoping it would do, it would simply test if abc == true). There is no way to compare one thing to multiple things in Java.
It's Impossible in java, you can use Varargs:
public boolean checkAnything(Object args...){
for(Object obj args){
if(...)
}
return ....;
}
See also:
Varargs
String… parameter in Java
Its not possible to that in Java. Instead you can do something like this:-
public boolean checkForNulls(Object... args){
List<Object> test = new ArrayList<Object>(Arrays.asList(args));
return test.contains(null); // Check if even 1 of the objects was null.
}
If any of the items is null, then the method will return true, else it'll return false. You can use it as per your requirements.
IMHO First is the better way and possible way.
Coming to second way ..if they are boolean values
if(abc && xyz )
{//...}
I was looking through the code for an old Android application of mine, and I saw one thing I did to the effect of this:
boolean emptyArray = true;
for (int i = 0; i < array.size(); i++)
{
if (array.get(i) != null)
{
emptyArray = false;
break;
}
}
if (emptyArray == true)
{
return true;
}
return false;
There has to be a more efficient way of doing this -- but what is it?
emptyArray is defined as an ArrayList of Integers, which are inserted with a random number of null values (And later in the code, actual integer values).
Thanks!
Well, you could use a lot less code for starters:
public boolean isAllNulls(Iterable<?> array) {
for (Object element : array)
if (element != null) return false;
return true;
}
With this code, you can pass in a much wider variety of collections too.
Java 8 update:
public static boolean isAllNulls(Iterable<?> array) {
return StreamSupport.stream(array.spliterator(), true).allMatch(o -> o == null);
}
There is no more efficient way.
The only thing is you can do, is write it in more elegant way:
List<Something> l;
boolean nonNullElemExist= false;
for (Something s: l) {
if (s != null) {
nonNullElemExist = true;
break;
}
}
// use of nonNullElemExist;
Actually, it is possible that this is more efficient, since it uses Iterator and the Hotspot compiler has more info to optimize instead using size() and get().
It's not detection of contains only null values but it maybe be enough to use just contains(null) method on your list.
Simply Check it worked for me. Hope will work fine for you too!
if (arrayListSubQues!=null){
return true;}
else {
return false }
I use to do something like this :
// Simple loop to remove all 'null' from the list or a copy of the list
while array.remove(null) {
array.remove(null);
}
if (CollectionUtils.isEmpty(array)) {
// the list contained only nulls
}