Fast ordered list matching algorithm in Java - java

I have a list of rules in the form
L1 -> (A, B, C)
L2 -> (D, E),
L3 -> (F, G, A),
L4 -> (C, A)
.....
This list contains ~30k such rules.
I have an input in the form (X, Y, Z)
This creates a method
List <Rule> matchRules(input)
Which belongs to a class RuleMatcher
I started with a very simple clear naive solution, in order to get the framework down, get something working.
public RuleMatcher(Collection<Rule> rules) {
this.rules = rules;
}
public Collection<Rule> matchRules(List<Token> input) {
List<Rule> matchingRules = new ArrayList<>();
for(Rule r: this.rules) {
if(r.matches(input)) {
matchingRules.add(r);
}
}
return matchingRules;
}
Where matches is a very simple function that checks if the lengths are the same, and then checks each token as a for loop.
This matchRules function is called in the magnitude of billions of times.
Obviously this is a very poor implementation. According to my profiler at least half of the execution time is is spent in this matches function.
I was thinking of two possible solutions:
A. Some sort of Trie data structure holding the chains of rules which could be matched.
B. some sort of hash function. Each symbol is given a unique identifier. Unfortunately, there are about 8 thousand unique symbols so this might be difficult.
C. Make a hashmap conditioning on the size of the right hand side, the number of tokens in the rule. Unfortunately, the majority of the rules are about the same size, so this may not even be worthwhile.
D. Some awesome solution one of you come up with.
I hope somebody can shed some light on this problem.
Edit: A token is just an object with a unique number. For example "NN" is a token. Each instance of "NN" is exactly the same.
Matches code:
public boolean rhsMatches(List<Token> tokens) {
if(tokens.size()!=rhsSize()) return false;
for(int i = 0;i<rhsSize();i++) {
if(!rightSide.get(i).equals(tokens.get(i)) {
return false;
}
}
return true;
}
Its not very pretty, but its simple.

Why not sort your rule list to begin with. Then you can binary search for the matching rule.

To me it looks like a perfect scenario for engaging some worker threads.
Tasks of matching seem independent of each other, divide the list of rules and delegate the matching to workers, if its possible in your situation.

Related

Validating an object with a long list of predicates

I have an object, Bill, with a number of fields. In the method below, I get the bill with a function. I want to validate it with a list of Predicate<Bill>, which are paired with the appropriate error message to be applied if the predicate test fails. How can I accumulate the error messages given a list of tests, given that I can have more than eight conditions, and therefore won't be able to use Validation.combine?
default Validation<Seq<String>, Long> validate(
Long id,
Long, Bill> getBill,
List<Pair<Predicate<Bill>,String>> tests){
Bill bill = getBill.apply(id);
//I want to do the same thing
//but using the list I passed in,
//without the limitation of eight validations.
return Validation.combine(
validateBill(bill, Pair.of(hasDateInsurerReceivedBill, "Date Insurer Received Bill absent")),
validateBill(bill, Pair.of(EventValidation.hasEmployeeIdNumber, "Employee ID Number absent"))
).ap((x, y) -> id);
}
default Validation<String,Long> validateBill(
Bill bill, Pair<Predicate<Bill>, String> condition)
{
return condition.getFirst().test(bill) ?
Validation.valid(bill.getIntId())
: Validation.invalid(condition.getSecond());
}
I'm brand new to this library and I'm not terribly familiar with functional programming yet, so please use examples and the simplest terminology possible in any explanations.
I would do a nested combine and then flatten the results.
In our project we always have Seq<ValidationError> on the left side of a Validation, you don't have to but it is good to understand the code I'll show you.
With the first 8 Validations you return a new Validation in the .ap
When you return a Validation inside .ap you will end up with something like this:
Validation<Seq<ValidationError>, Validation<Seq<ValidationError>, String>> x = ...
The needs to be flattened with the following piece of code:
Validation
.combine(step1, step2, step3, step4, step5, step6, step7, step8)
.ap((a, b, c, d, e, f ,g, h) -> {
// do important stuff and
return Validation......
})
.mapError(Util::flattenErrors)
.fold(Validation::invalid, Function.identity());
The Util class:
public static Seq<ValidationError> flattenErrors(final Seq<Seq<ValidationError>> nested) {
return nested
.flatMap(Function.identity())
.distinct(); //optional duplicate filtering
}
With this new validation you can do the same trick again (you can add 7 new validations every time or create a few and do another combine, depends a bit on the number of validations you have).

Atomically searchKeys() and put() in a ConcurrentHashMap

I am developing a web server in java which, among other things, is supposed to implement a challenge service between couples of users.
Each user can compete in only one challenge at a time.
Actually I am storing the "Challenge" objects in a ConcurrentHashMap<String, Challenge> and I am using a String that is the union of the two players usernames as keys for mappings.
For example, if the usernames of the two players are "Mickey" and "Goofy" then the key of the Challenge object inside the ConcurrentHashMap will be the string:
Mickey:Goofy
When recording a new challenge between two users in the ConcurrentHashMap, i have to check if they are already engaged in others challenges before actually putting the challenge in the Map, in other words, i have to check if there is a key stored in the Map that contains one of the two usernames of the players which want to start the new challenge.
For example, given a filled ConcurrentHashMap<String, Challenge> and a challenge request for the users Mickey and Goofy, i want to know in an atomic way and without locking whole map, if one (or eventually both) of them is/are already engaged in other registered challenge within the Map and if not, then put the new Challenge in the Map.
I hope to have been clear enough.
Do any of you have a suggestion?
Thanks in advance.
Using string concatenation is a bad choice for a compound key. String concatenation is an expensive operation and it doesn’t guaranty uniqueness, as the key becomes ambiguous when one of the strings contains the separator of your choice.
Of course, you can forbid that particular character in user names, but this adds additional requirements you have to check, whereas a dedicated key object holding two references is simpler and more efficient. You may even use a two element List<String> as an add-hoc key type, as it has useful hashCode and equals implementations.
But since you want to perform lookups for both parts of the compound key anyway, you should not use a compound key in the first place. Just associate both user names with the same Challenge object. This still can’t be done in a single atomic operation, but it doesn’t need to:
final ConcurrentHashMap<String, Challenge> challenges = new ConcurrentHashMap<>();
Challenge startNewChallenge(String user1, String user2) {
if(user1.equals(user2))
throw new IllegalArgumentException("same user");
Challenge c = new Challenge();
if(challenges.putIfAbsent(user1, c) != null)
throw new IllegalStateException(user1+" has an ongoing challenge");
if(challenges.putIfAbsent(user2, c) != null) {
challenges.remove(user1, c);
throw new IllegalStateException(user2+" has an ongoing challenge");
}
return c;
}
This code will never overwrite an existing value. If both putIfAbsent were successful, both user definitely had no ongoing challenge and are now both associated with the same new challenge.
When the first putIfAbsent succeeded but the second fails, we have to remove the first association. remove(user1, c) will only remove it when the user still is associated with our new challenge. When all operations on the map follow the principle to never overwrite an existing entry (unless all prerequisites are met), this is not necessary, a plain remove(user1) would do as well. But it doesn’t hurt to use the safe variant here.
The only issue with the non-atomicity is that two overlapping attempts involving the same user could both fail, due to the temporarily added first user, when actually one of them could succeed. I do not consider that a significant problem; the user simply shouldn’t attempt to join two challenges at the same time.
You must review your code.
You cannot do this in one time as you have two names to check.
Even in a conventional (iterating) way you would have in the best case two operation.
So anyway you will need to do at least two access on the map.
I suggest you to use your actual map without the concatenation of strings, so yes, one Challenge will appear two time in the map, one for each participant. Then you will be able to check easily if a user is engaged.
If you need to know with whom he is engaged, simply store the both names in the Challenge class.
Of course lock your map when you are looking for both entries. A function who return a Boolean will do the job !
From my perspective it's possible, but the map has to use individual player names as keys, so for both players we have to put one challenge twice.
Having this, we can introduce additional async checking whether the new challenge was successful stored for the both players.
private boolean put(Map<String, Challenge> challenges, String firstPlayerName,
String secondPlayerName,
Challenge newChallenge) {
if(firstPlayerName.compareTo(secondPlayerName) > 0) {
String tmp = firstPlayerName;
firstPlayerName = secondPlayerName;
secondPlayerName = tmp;
}
boolean firstPlayerAccepted = newChallenge == challenges.merge(firstPlayerName, newChallenge,
(oldValue, newValue) -> oldValue.isInitiated() ? oldValue : newValue);
boolean secondPlayerAccepted = firstPlayerAccepted
&& newChallenge == challenges.merge(secondPlayerName, newChallenge,
(oldValue, newValue) -> oldValue.isInitiated() ? oldValue : newValue);
boolean success = firstPlayerAccepted && secondPlayerAccepted;
newChallenge.initiate(success);
if (firstPlayerAccepted) {
// remove unsuccessful
challenges.computeIfPresent(firstPlayerName, (s, challenge) -> challenge.isInitiated() ? challenge : null);
if (secondPlayerAccepted) {
challenges.computeIfPresent(secondPlayerName, (s, challenge) -> challenge.isInitiated() ? challenge : null);
}
}
return success;
}
class Challenge {
private final CompletableFuture<Boolean> initiated = new CompletableFuture<>();
public void initiate(boolean success) {
initiated.complete(success);
}
public boolean isInitiated() {
try {
return initiated.get();
} catch (ExecutionException e) {
throw new IllegalStateException(e);
} catch (InterruptedException e) {
return false;
}
}
enter code here
...
}

In Java, a "decorate and sort" concise implementation?

I'm learning Java for the first time (my prior experience is Python and Haskell). I have a situation that would, in Python, require a "decorate and sort" idiom. Such as the following (code not tested but this is roughly correct):
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
By choosing a different evalFunc you can choose how this is sorted.
In Java, I'm writing a program that composes music by choosing from among a list of notes, evaluating the "fitness" of each note, and picking the best. I have a class representing musical notes:
class Note {
...
}
I have a class that represents the fitness of a note as two values, its goodness and badness (yes, these are separate concepts in my program). Note: in Python or Haskell, this would simply be a 2-tuple, but my understanding is that Java doesn't have tuples in the usual sense. I could make it a pair, but it gets unwieldy to declare variables all over the place like List<Pair<Type1,Pair<Type2,Type3>>>. (As an aside, I don't think Java has type aliases either, which would let me shorten the declarations.)
class Fitness {
double goodness;
double badness;
}
The function that evaluates the fitness needs access to several pieces of data other than the Note. We'll say it's part of a "Composition" class:
class Composition {
... data declared here ... ;
public Fitness evaluate(Note n) {
}
}
I'd like to be able to compare Fitness objects in numerical order. There are two ways to compare: either goodness or badness can be numerically compared, depending on the situation.
class CompareFitnessByGoodness implements Comparator<Fitness> {
}
class CompareFitnessByBadness implements Comparator<Fitness> {
}
I'd like to package the Note together with its fitness, so I can sort the combined list by fitness and later pull out the best Note.
class Together {
public Note;
public Fitness;
}
I'd like to sort a List<Together> by either the goodness, or by the badness. So I might need:
class CompareTogetherByGoodness implements Comparator<Together> {
...
}
class CompareTogetherByBadness implements Comparator<Together> {
...
}
Eventually I'll write something like
Note pickBest(List<Together> notes) {
// Pick a note that's not too bad, and pretty good at the same
// time.
// First sort in order of increasing badness, so I can choose
// the bottom half for the next stage (i.e. the half "least bad"
// notes).
Collections.sort(notes, new CompareTogetherByBadness());
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
// Now sort `leastBadHalf` and take the last note: the one with
// highest goodness.
Collections.sort(leastBadHalf, new CompareTogetherByGoodness());
return leastBadHalf.get(leastBadHalf.size()-1);
}
Whew! That is a LOT of code for something that would be a few lines in Haskell or Python. Is there a better way to do this?
EDIT:
Addressing some of the answers.
"You don't need to decorate." Well, my fitness computation is very expensive, so I want to compute it once for each note, and save the result for later access as well.
"Store goodness/badness in Note." The goodness or badness is not a property of the note alone; it's only meaningful in context and it can change. So this is a suggestion that I add mutable state which is only meaningful in some contexts, or plain wrong if there's a bug which accidentally mutates it. That's ugly, but maybe a necessary crutch for Java.
Going by what you already have
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
This is the equivalent in modern Java:
Given your composition object:
Composition composer = ...;
And a list of notes:
List<Note> notes = ...;
Then you can do:
List<Together> notesAllTogetherNow = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByGoodness())
.collect(Collectors.toList());
To get the best note, you can take a bit further:
Optional<Note> bestNote = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByBadness())
.limit(notes.size() / 2) // Taking the top half
.sorted(new CompareTogetherByGoodness())
.findFirst() // Assuming the last comparator sorts in descending order
.map(Together::getNote);
You can use streams:
Function<Foo, Bar> func = ...
Comparator<Foo> comparator = ...
var list = ...
var sorted = list.stream()
.sorted(comparator)
.map(func)
.collect(Collectors.toList());
Java plainly includes a Collections.sort :: List -> Comparator -> List that does everything for you. It mutates the original list, though.
Unfortunately, Java's standard library does not include tuples and even a plain Pair; the Apache Commnons library does, though.
In short, you don't need the decorate / undecorate approach in Java.
class Fitness {
double goodness;
double badness;
}
class Together {
Note note;
Fitness fitness;
}
class Note{
}
List<Together> notes = ...
Collections.sort(notes, Comparator.comparingDouble(value -> value.fitness.badness));
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
return leastBadHalf.stream().max(Comparator.comparingDouble(value -> value.fitness.goodness));

How to collect results after filtering and mapping a parallelStream in Java8?

I want to extract a collection of objects from another collection. The objects to be filtered must be a specific type (or subtype) and must intersect with a given Shape. I want to do it with parallelStream
I have the following code:
public class ObjectDetector {
...
public ObjectDetector(final Collection<WorldObject> objects,
final BiFunction<Shape, Shape, Boolean> isIntersecting) {
...
}
public List<ISensor> getSonarObjects(final Shape triangle) {
return selectIntersecting(triangle, ISensor.class);
}
private <T> List<T> selectIntersecting(Shape triangle, Class<T> type) {
return objects.parallelStream()
.filter(o -> type.isInstance(o) && isIntersecting.apply(o.getShape(), triangle))
.map(o -> type.cast(o)).collect(Collectors.toList());
The problematic part is in the List<T> selectIntersecting(Shape triangle, Class<T> type) method, in which objects is a Collection and isIntersecting is a BiFunction<Shape,Shape,Boolean>.
When I'm using stream() instead of parallelStream() all my tests are green. So I may assume that the filtering and mapping logic works fine. However when I am trying to use the parallelStream() my tests are failing unpredictably. The only coherence that I was able to observe is that the size() of the returned List<T> is less than or equal to (but of course never greater) the size I expect.
A failing testcase for example:
int counter = 0;
public BiFunction<Shape, Shape, Boolean> every2 = (a, b) -> {
counter++;
return counter % 2 == 0 ? true : false;
};
#Test
public void getEvery2Sonar() {
assertEquals("base list size must be 8",8,list.size());
ObjectDetector detector = new ObjectDetector(list, every2);
List<ISensor> sonarable = detector.getSonarObjects(triangle);
assertEquals("number of sonar detectables should be 3", 3, sonarable.size());
}
And the test result is:
Failed tests: getEvery2Sonar(hu.oe.nik.szfmv.environment.ObjectDetectorTest): number of sonar detectables should be 3 expected:<3> but was:<2>
In my understanding - as it is written here - it is possible to collect a parallelStream into non-concurrent Collection.
I've also tried to find some clues on the Parallelism tutorial page, but I'm still clueless.
Could someone please provide me an explanation about what am I doing wrong?
Your predicate function has side effects - this is going to go badly with parallelStream because the evaluation order across the input stream is non-deterministic, plus you have no locking on your mutable state.
Indeed, the documentation for filter states* that the predicate must be stateless.
I'm not sure what behaviour you're trying to achieve here, so I'm not sure what an appropriate "fix" might be.
* No pun intended.

Should I minimize the number of "if" statements or "for" loops?

I have a list of Objects that need to have multiple, conditionally applied, operations applied to each element. Is it more efficient to take a "if-for" approach or a "for-if" approach. To put it another way, should I minimize the number of if statements or the number of for loops? Is there a standard for this?
What would be a good reliable way to determine this?
"If-For" to Approach minimize if statements
public void ifForMethod() {
if (conditionA) {
for (Object o : listOfObjects) {
doA(o);
}
}
if (conditionB) {
for (Object o : listOfObjects) {
doB(o);
}
}
}
"For-If" Approach to minimize for loops
public void forIfMethod() {
for (Object o : listOfObjects) {
if (conditionA) {
doA(o);
}
if (conditionB) {
doB(o);
}
}
}
Assumptions
The conditions are simple booleans and will not change while iterating.
One or more conditions will be true. (there are more than 2 conditions)
Each condition is independent of the other conditions.
The inner methods do not conflict or interact with each other at all. The order in which they are executed is irrelevant.
There is no reason to make 2 passes over the list.
Assumptions: predicates are simple booleans, if they have to be evaluated then obviously the cost can change things.
If ((condtionA || conditionB) == true) then both If-for and For-If are both 1 pass. If both predicates can be true then obviously you only want to make one pass.
It doesn't matter what doA and doB since we're assuming they're they same in both If-for and For-If.
If the predicates can change over the course of evaluation then that must be considered.
You're asking a general question so answers are general and vague without more details.
Ok now that you've provided additional info (the list is only 5 elements long, this is part of a build process, the predicates are static booleans) we can see that the bottleneck here is the doA/B functions. Therefore you should only go through the loop once. The static boolean checks are negligible.
Using what you called the "If-For" way rather than "For-If" is (perhaps a slightly more general version of) an optimization called loop unswitching. Whether it's actually a good idea depends on several factors, such as (but not limited to)
whether that transformation is even allowed (ie conditions have no side effects and doA and doB may be reordered)
what you're optimizing for (eg speed, readability, or w/e) though in this case that doesn't really make a difference
whether the array fits in cache (iterating over it twice could double the number of cache misses)
what the (JIT) compiler makes of it exactly, for example whether the conditions actually compile to branches or not or maybe the compiler does the loop unswitching for you
the processor microarchitecture (some µarchs dislike branches inside loops more than others, even if those branches are highly predictable)
First, let's take a look at the complexity of the methods that you've shown so far:
The ifForMethod performs k checks, m of which return true. For each of these m, there is an iteration over n objects. The complexity, then, is k+nm.
The forIfMethod iterates over n objects and performs k comparisons on each iteration. The complexity, then, is k+n(k-1)=nk.
In both cases, all k conditions have to be evaluated at least once, so the difference here really is in the nm and n(k-1) addends. Asymptotically, m is a just a fraction of k (you said m is approximately .75k), so these are both O(nk), but k+nm < k+n(k-1), so the ifForMethod might be a faster than forIfMethod. The difference in actual run time is going to depend on factors such as the actual time that it takes to iterate over the array, as well as the magnitude of k. You're going to start getting into issues such as memory locality (both for your objects as well as your code).
Here's an approach that you might find interesting, though. Ideally, you'd only want to iterate through the list of objects once, and you wouldn't want to have to check the boolean conditions multiple times. You could abstract away the actions that you're performing in such a way that you could combine them into a single action (and you'd only incorporate those actions that correspond to the conditions that are true), and then perform that compound action on each element in the list. Here's some code that does this.
The idea is that there are Actions, and that you can construct an Action that performs doA and an Action that performs doB. Based on the conditions, you can create a compound action that includes the doA action if the doA condition is true, and the doB action if the doB condition is true. Then you iterate through the objects, and call perform the compound action on each object. Asymptotically, this is a k+nm method, so in theory it performs nicely, but again, the actual performance here will depend on some of those tricky constants, and memory locality issues.
import java.util.ArrayList;
import java.util.List;
public class CompoundActionExample {
/**
* An action is used to do something to an argument.
*/
interface Action {
void act( Object argument );
}
/**
* A compound action is an action that acts on an argument
* by passing the argument to some other actions.
*/
static class CompoundAction implements Action {
/**
* The list of actions that the compound action will perform. Additional
* actions can be added using {#link #add(Action)}, and this list is only
* accessed through the {#link #act(Object)} method.
*/
private final List<CompoundActionExample.Action> actions;
/**
* Create a compound action with the specified list of actions.
*/
CompoundAction( final List<CompoundActionExample.Action> actions ) {
this.actions = actions;
}
/**
* Create a compound action with a fresh list of actions.
*/
CompoundAction() {
this( new ArrayList<CompoundActionExample.Action>() );
}
/**
* Add an action to the compound action.
*/
public void add( CompoundActionExample.Action action ) {
actions.add( action );
}
/**
* Act on an argument by passing the argument to each of the
* compound action's actions.
*/
public void act( final Object argument) {
for ( CompoundActionExample.Action action : actions ) {
action.act( argument );
}
}
}
public static void main(String[] args) {
// Some conditions and a list of objects
final boolean conditionA = true;
final boolean conditionB = false;
final Object[] listOfObjects = { "object1", "object2", "object3" };
// A compound action that encapsulates all the things you want to do
final CompoundAction compoundAction = new CompoundAction();
// If conditionA is true, add an action to the compound action that
// will perform doA. conditionA is evaluated exactly once.
if ( conditionA ) {
compoundAction.add( new Action() {
public void act( final Object argument) {
System.out.println( "doA("+argument+")" ); // doA( argument );
}
});
}
// If conditionB is true, add an action to the compound action that
// will perform doB. conditionB is evaluted exactly once.
if ( conditionB ) {
compoundAction.add( new Action() {
public void act(Object argument) {
System.out.println( "doB("+argument+")" ); // doB( argument );
}
});
}
// For each object, apply the compound action
for ( final Object o : listOfObjects ) {
compoundAction.act( o );
}
}
}
It Depends on the nature of the business problem your code is trying to solve. If both conditionA AND conditionB are simple Boolean variables but not expressions, then the For-If is going to be better as you are cycling through the list of objects only once.
We are basically comparing which performs better : Enumerating from a list of objects multiple times or evaluating a boolean expression multiple times. If your conditionA/conditionB are very complex Boolean expressions, then your If-For would be a better approach.
lets consider that we are doing same number of operation in both the for loop and inside if .With this standard i will go with the first approach which using if statement before executing for loop just to avoid the number of iteration in for loop.
Also as you are using advance for loop which takes more time to execute the same operation compare to normal for loop.
please correct me if i am wrong.
It depends! The ifForMethod() solution is best, if there are real cases where neither conditionA nor conditionB is true. If there are cases where conditionA and conditionB are true, solution forIfMethod() is the best but the conditions should be precalculated before entering the loop.
But you can modify forIfMethod() to make it suitable for all cases:
public void forIfMethod() {
boolean a = conditionA;
boolean b = conditionB;
if (a || b) {
for (Object o : listOfObjects) {
if (a) {
doA(o);
}
if (b) {
doB(o);
}
}
}
}
the first one (if-for) sounds good for me.. because for first case there will be a single checking for whole for loop. But in the second cases there will be checking for every loop.
The second one is more efficent in terms of how many comparisons you make.
Check condition a, 1 calculation.
If true, Object.size calculatons.
Check condition b, 1 calculation.
If true, Object.size calculations.
Min, 2, Max Object.size * 2
For Method 2, you will always have Object.size * 2 calculations performed.
Consider your "worst case" if both checks are false. Way 1 will only do 2 calculations. Way 2 will perform Object.size * 2. It has nothing to do with your function as in both cases it will always take the same amount of time in both cases.
Even in your "best case" if both checks are true, you are still performing that check N-1 times more for A, and N-1 times more for B.
Best way I think to do it with the fewest calculations.
public void ifForMethod() {
if (conditionA) {
if(conditionB){
for (Object o : listOfObjects) {
doA(o);
doB(o);
}
else{
for (Object o : listOfObjects) {
doA(o);
}
}
}
else if (conditionB) {
for (Object o : listOfObjects) {
doB(o);
}
}
}
You perform 2 check operations and then only loop through the list once, at max.
I think it depends on more things, like: If you find the conditionA, will the loop break? The conditionA and conditionB can coexist? Could I use if-else with them?
Just looking for what you've presented, I think the second aproach is better. You're only looping once and checking twice in the same loop. In my opinion it's also more readable.
Several things:
Is this a premature optimization? Does it really matter if one way is faster than the other, depending on the data it might not be a human noticeable difference.
I would question the design of the software. Why is the same Object have 2 possible conditions? I would recommend breaking the design into multiple objects. Perhaps using subclasses to do the different logic or use the Strategy Pattern. I can't be more specific without a better idea of what you are doing.

Categories