public class IDS{
public String id;
public long startTime;
public long endTime;
}
List<IDS> existingIDS = new ArrayList<IDS>();
List<IDS> newIDSToWrite = new ArrayList<IDS>();
I want to merge the newIDSToWrite values with existingIDS values, with newIDSToWrite values taking precedence if a conflict occurs.
existingIDS has values like this (id1,4,7) (id2,10,14) (id3,16,21)
newIDSToWrite has values like this (id4,1,5) (id5,8,9) (id6,12,15) (id7,18,20)
If the newIDSToWrite above is merged with existingIDS result should be like (id4,1,5) (id1,5,7) (id5,8,9) (id2,10,12) (id6,12,15) (id3,16,18) (id7,18,20) (id3,20,21)
Whats the best way of doing this?
You can use the method List.retainAll():
existingIDS.retainAll(newIDSToWrite);
Link to the doc.
UPDATE:
Good comment by dasblinkenlight: in class ID you should override hash() and equals() methods in order to achieve a correct behavior (two IDs that are created with the same values should be equal even if they don't point to the same object in the heap).
You can also use apache commons ListUtils
ListUtils.union(existingIDS ,newIDSToWrite );
You can find the documentation here.
For the second part of the question you can use the same logic as the question you has asked earlier but a little modification
delete intersecting values in an arraylist
(1, 3) (2, 4) (5, 6)
curmax = -inf
curmax = 3
2 < 3 - mark first and second as "bad". curmax = 4
Update value of 2 to (3+1)
5 > 4 - do nothing. curmax = 6.
(5,6) - is the only good segment.
I recommend something like this (note that it may not compile directly since I wrote it quickly). This code basically makes your class more object oriented and requires the object be initialized with a valid id. As other mentioned above, you must implement hashCode() and equals() to be able to properly compare objects and check if an object is contained within a collection (I usually have eclipse generate these functions for me upon selecting fields):
public class IDS {
private String id;
private long startTime;
private long endTime;
public IDS(String id){
if(id == null) throw new Exception("RAII failure: IDS requires non-null ID");
this.id = id;
}
// id - getter
// startTime, endTime - getters/setters
public boolean equals(IDS otherId){
if(otherId == null) return false;
return otherId.getId().equals(getId());
}
}
List<IDS> existingIDS = new ArrayList<IDS>();
List<IDS> newIDSToWrite = new ArrayList<IDS>();
Set<IDS> mergedIds = new HashSet<IDS>(newIDSToWrite);
for(IDS id : existingIDS){
if(!mergedIds.contains(id)) mergedIds.add(id);
}
Related
I have a java class with 3 boolean property like this
boolean isActive;
boolean isEnable;
boolean isNew;
every property is related to an enum (e.g. ACTIVE,ENABLE,NEW).
I want to have 2 lists of enum. One which has only the enums related to true property value and one for the false one.
just to be clear. using if-else statement I could have
Set<FlagEnum> flagSet = new HashSet<>();
Set<FlagEnum> falseFlagSet = new HashSet<>();
if (object.isActive()) {
flagSet.add(ACTIVE);
} else {
falseFlagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
} else {
falseFlagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
} else {
falseFlagSet.add(NEW);
}
is there a way to avoid all these if-else?
I tried with something like
Map<boolean, List<Pair<boolean, FlagEnum>>> res = Stream.of(
new Pair<>(object.isActive(), ACTIVE),
new Pair<>(object.isNew(), NEW),
new Pair<>(object.isEnable(), ENABLE))
.collect(Collectors.partitioningBy(Pair::getKey));
but the resulted structure is an additional complexity which I would like to avoid.
In my real case, I have more than 15 boolean properties...
You can simplify this in various ways. Which of them make sense, depends on your exact requirements.
You can derive the falseFlagSet trivially from the flagSet using EnumSet.complementOf after populating the flagSet:
EnumSet<FlagEnum> falseFlagSet = EnumSet.complementOf(flagSet);
This assumes that all FlagEnum values have corresponding flags. If that's not the case then you need to construct a EnumSet with all enums that have flags and subtract flagSet from that using removeAll.
#1 already removes the need for the else in your cascade, simplifying the code to
if (object.isActive()) {
flagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
}
If you have enough different flags, then you can create a mapping from getter method to FlagEnum value like this:
Map<Function<YourClass,Boolean>,FlagEnum> GETTERS = Map.of(
YourClass::isActive, FlagEnum.ACTIVE,
YourClass::isNew, FlagEnum.NEW,
YourClass::isEnable, FlagEnum.ENABLE);
Then you can use this to make the whole process data-driven:
EnumSet<FlagEnum> getFlagSet(YourClass yourObject) {
EnumSet<FlagEnum> result = EnumSet.noneOf(FlagEnum.class);
for (Map.Entry<Function<YourClass,Boolean>, FlagEnum> getter : GETTERS.entrySet()) {
if (getter.getKey().apply(yourObject)) {
result.add(getter.getValue());
}
}
return result;
}
If the number of flags is very big, then you could switch entirely to reflection and detect the flags and matching getters dynamically using string comparison, but I would not suggest that approach. If you need something like that then you probably should switch to a framework that supports that kind of feature and not implement it yourself.
That last two obviously only makes sense when the number of flags is big. If it's actually just 3 flags, then I wouldn't mind and just have 3 simple if statements.
As a slight tangent: GETTERS above should definitely be an immutable map (wrap it in Collections.unmodifiableMap or use something like Guava ImmutableMap) and it could be argued that the same applies to the return value of the getFlagSet method. I've left those out for succinctness.
You can use a private helper method for this.
private void addFlagSet(boolean condition, FlagEnum flagEnum,
Set<FlagEnum> flagSet, Set<FlagEnum> falseFlagSet) {
Set<FlagEnum> chosenFlagSet = condition ? flagSet: falseFlagSet;
chosenFlagSet.add(flagEnum);
}
Call it as:
addFlagSet(object.isActive(), FlagEnum.ACIVE, flagSet, falseFlagSet);
addFlagSet(object.isNew(), FlagEnum.NEW, flagSet, falseFlagSet);
addFlagSet(object.isEnable(), FlagEnum.ENABLE, flagSet, falseFlagSet);
You could probably use Reflection to get all methods, then check if a getReturnType() == boolean.class. Problem is the connection between the method's name and the enum. If every single one is named like the method without the 'is', you could use FlagEnum.valueOf() to retrieve the enum value from the method name and use it.
I think this could be the easiest and clearest way to do what I need
Map<Boolean, Set<FlagEnum>> flagMap = new HashMap<>();
flagMap.computeIfAbsent(object.isActive(), h -> new HashSet()).add(ACTIVE);
flagMap.computeIfAbsent(object.isEnabled(), h -> new HashSet()).add(ENABLE);
flagMap.computeIfAbsent(object.isNew(), h -> new HashSet()).add(NEW);
//to get TRUE set simply :
flagMap.get(true);
what do you think?
I'm working on a small program to compare service levels, the user will input the service level 2 times (current and requested) and then the input will be scanned and compared and show a message.
For example:
current = 9*5 NBD (a)
requested = 24*7 SBD (b)
I want to know how in Java I can tell the compiler that (b) is greater than (a)
Because I want to use if statement like this
if (b > a) then show message.
I tried to use string.equals, but didn't help me too much.
I was not successful to convert string to number to do such comparison.
Try following statement
if(a.compareTo(b) > 0);
First thing: you can't override String.compareTo(), because it's final. you can create class with String field and write compareTo() for this class. This is not best idea.
But you can compare two strings by putting them into array and creating implementation of Comparator interface in sort() method.
String current = "9*5 NBD";
String requested = "24*7 SBD";
String[] test = {current, requested};
Arrays.sort(test, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
//Your impl goes here
return 0;
}
});
Where do these strings come from? Surely they must be from some kind of table that contains the service level details together with the cost of subscribing to that service level. What you want to check is whether the required service level costs more than the service level the client already has. Suppose the service level details come from a Map<ServiceLevel, BigDecimal> that gives the cost for a certain service level. Then all you need to do is:
BigDecimal costOfCurrentSL = serviceLevelCosts.get(currentSL);
BigDecimal costOfRequiredSL = serviceLevelCosts.get(requiredSL);
if (costOfRequiredSL.compareTo(costOfCurrentSL) > 0) {
// ... tell client he needs to purchase a top-up
}
Thank you all for the willing to help :)
After a lot of thinking I found another way which helped me a lot
I created 2 new integers and called them Values of what I need.
and used if statement, that if the entered is 9*5 NBD so the value will be zero, and if it is SBD, the value will be 1 and so on, then created new if statement to compare the values and show me a message if the A is greater than B, and it really worked.
Here is a part of my code
String WA_SLA = "", REQ_SLA = "";
int Va_WA_SLA = 0, Va_REQ_SLA = 0;
if(WA_SLA.equalsIgnoreCase("9*5 SBD"))
{
Va_WA_SLA = 1;
}
if(REQ_SLA.equalsIgnoreCase("9*5 NBD"))
{
Va_REQ_SLA = 0;
}
if(Va_WA_SLA > Va_REQ_SLA)
{
JOptionPane.showMessageDialog(frame,"Warranty SLA is Higher than Requested SLA " ,null, JOptionPane.INFORMATION_MESSAGE);
}
Thaaaaaaaaaaaaank you a lot
Just for the sake of a thought exercise, how could the uniqueness of an attribute be enforced for each instance of a given class ?
Uniqueness here can be defined as being on a single JVM and within a single user session.
This is at Java-level and not to do with databases, the main purpose being to verify if a collision has occurred.
The first obvious step is to have a static attribute at class level.
Having an ArrayList or other container seems impractical as the number of instances rises.
Incrementing a numeric counter at class level appears to be a simplest approach but the id must always follow the last-used-id.
Enforcing a hash or non-numeric id could be problematic.
Concurrency might be of concern. If it is possible for two instances get an id at the same time then this should be prevented.
How should this problem be tackled ? What solutions/approaches might already exist ?
If you care about performance, here is a thread safe, fast (lock-free) and collision-free version of unique id generation
public class Test {
private static AtomicInteger lastId = new AtomicInteger();
private int id;
public Test() {
id = lastId.incrementAndGet();
}
...
Simply use the UUID class in Java http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html. Create a field of the type UUID in the classes under inspection and initialize this field in the constructor.
public class Test {
public UUID id;
public Test() {
id = UUID.randomUUID();
}
}
When it comes time for detecting collisions, simply compare the string representations of the UUIDs of the objects like this ...
Test testObject1 = new Test();
Test testObject2 = new Test();
boolean collision = testObject1.id.toString().equals(testObject2.id.toString());
Or more simply use the compareTo() method in the UUID class ...
boolean collision = testObject2.id.compareTo(testObject1.id) == 0 ? true : false;
0 means that the ids are the same. +1 and -1 when they are not equal.
Merit: universally unique (can be time based, random) and hence should takes care of threading issues (some one should confirm this ... this is based off the best of my knowledge). more information here and here.
To make it thread-safe refer to this question on SO is java.util.UUID thread safe?
Demerit: will require a change in the structure of the classes under inspection, i.e. the id field will have to added in the source of the classes themselves. which might or might not be convenient.
UUID is a good solution, but UUID.randomUUID() on the backend use method:
synchronized public void SecureRandom.nextBytes(byte[] bytes)
So this is slow: threads lock a single monitor object in each id generation operation.
The AtomicInteger is better, because it loops in a CAS operation. But again, for each id generation operation a synchronization operation must be done.
In the solution below, only prime numbers generation is synchronized. Synchronization is on a volatile int, so is fast and thread-safe. Having a set of primes, many ids are generated in a iteration.
Fixed number of threads
Edit: Solution for fixed number of thread
I you know apriory how many threads will use the Id generation, then You can generate IDs with values
Id = I mod X + n*X
Where X is the number of threads, I is the thread number, and N is a local variable that is incremented for each Id generation. The code for this solution is really simple, but it must be integrated with the hole program infrastructure.
Ids generated from primes
The idea is to generate the ids as factors of prime numbers
id = p_1^f1 * p_2^f2 * p_2^f3 * ... * p_n^fn
We use different prime numbers in each thread to generate different sets of ids in each thread.
Assuming that we use primes (2,3,5), the sequence will be:
2, 2^2, 2^3, 2^4, 2^5,..., 2^64
Then, when we see that a overflow will be generated, we roll the factor to the next prime:
3, 2*3 , 2^2*3, 2^3*3, 2^4*3, 2^5*3,..., 2^62*3
and next
3^2, 2*3^2 , 2^2*3^2, .....
Generation class
Edit: primer order generation must be done on AtomicInteger to be correct
Each instance of class IdFactorialGenerator will generate different sets of ids.
To have a thread save generation of Ids, just use ThreadLocal to have a per-thread instance setup. Synchronization is realized only during prime number generation.
package eu.pmsoft.sam.idgenerator;
public class IdFactorialGenerator {
private static AtomicInteger nextPrimeNumber = 0;
private int usedSlots;
private int[] primes = new int[64];
private int[] factors = new int[64];
private long id;
public IdFactorialGenerator(){
usedSlots = 1;
primes[0] = Sieve$.MODULE$.primeNumber(nextPrimeNumber.getAndAdd(1));
factors[0] = 1;
id = 1;
}
public long nextId(){
for (int factorToUpdate = 0; factorToUpdate < 64; factorToUpdate++) {
if(factorToUpdate == usedSlots) {
factors[factorToUpdate] = 1;
primes[factorToUpdate] = Sieve$.MODULE$.primeNumber(nextPrimeNumber.getAndAdd(1));
usedSlots++;
}
int primeToExtend = primes[factorToUpdate];
if( primeToExtend < Long.MAX_VALUE / id) {
// id * primeToExtend < Long.MAX_VALUE
factors[factorToUpdate] = factors[factorToUpdate]*primeToExtend;
id = id*primeToExtend;
return id;
} else {
factors[factorToUpdate] = 1;
id = 1;
for (int i = 0; i < usedSlots; i++) {
id = id*factors[i];
}
}
}
throw new IllegalStateException("I can not generate more ids");
}
}
To get the prime numbers I use a implementations on scala provided here in the problem 7: http://pavelfatin.com/scala-for-project-euler/
object Sieve {
def primeNumber(position: Int): Int = ps(position)
private lazy val ps: Stream[Int] = 2 #:: Stream.from(3).filter(i =>
ps.takeWhile(j => j * j <= i).forall(i % _ > 0))
}
I want to find out if StringTemplate have/support incrementation of a number.
Situation is:
input: is an array of objects which have "isKey() and getName()" getter.
output should be (i=0; IF !obj.getKey() THEN ps.setObject(i++,obj.getName)) ENDIF):
ps.setObject(1,"Name");
ps.setObject(2,"Name");
ps.setObject(3,"Name");
...
Currently I have next ST: <objs:{<if(it.key)><else>ps.setObject(<i>, <it.name;>);<"\n"><endif>}>
And the output in case if 1st is key:
ps.setObject(2,"Name");
ps.setObject(3,"Name");
ps.setObject(4,"Name");
...
Issue now I need to find a way to replace the 'i' with something which will be increment only when if condition is true.
PLS advice who faced this kind of issue!
In general, changing the state in response to ST's getting the state is not a good idea, so numbering non-key fields should happen in your model, before you start with the generation.
Add a getter for nonKeyIndex to the class of your model that hosts the name property. Go through all siblings, and number them as you need (i.e. starting from one and skipping the keys in your numbering). Now you can use this ST to produce the desired output:
<objs:{<if(it.key)><else>ps.setObject(<it.nonKeyIndex>, <it.name;>);<"\n"><endif>}>
Sometimes it may not be possible to add methods such as nonKeyIndex to your model classes. In such cases you should wrap your classes into view classes designed specifically to work with string template, and add the extra properties there:
public class ColumnView {
private final Column c;
private int nonKeyIdx;
public ColumnView(Column c) {this.c = c;}
public String getName() { return c.getName(); }
public boolean getKey() { return c.getKey(); }
public int getNonKeyIndex() { return nonKeyIdx; }
public void setNonKeyIndex(int i) { nonKeyIdx = i; }
}
I am using ConcurrentSkipListSet, which I fill with 20 keys.
I want to replace these keys continuously. However, ConcurrentSkipListSet doesn't seem to have an atomic replace function.
This is what I am using now:
ConcurrentSkipListSet<Long> set = new ConcurrentSkipListSet<Long>();
AtomicLong uniquefier = new AtomicLong(1);
public void fillSet() {
// fills set with 20 unique keys;
}
public void updateSet() {
Long now = Calendar.getInstance().getTimeInMillis();
Long oldestKey = set.first();
if (set.remove(oldestKey)) {
set.add(makeUnique(now));
}
}
private static final long MULTIPLIER = 1024;
public Long makeUnique(long in) {
return (in*MULTIPLIER+uniquefier.getAndSet((uniquefier.incrementAndGet())%(MULTIPLIER/2)));
}
The goal of this whole operation is to keep the list as long as it is, and only update by replacing. updateSet is called some 100 times per ms.
Now, my question is this: does remove return true if the element itself was present before (and isn't after), or does the method return true only if the call was actually responsible for the removal?
I.e.: if multiple threads call remove on the very same key at the very same time, will they /all/ return true, or will only one return true?
set.remove will only return true for the thread that actually caused the object to be removed.
The idea behind the set's concurrency is that multiple threads can be updating multiple objects. However, each individual object can only be updated by one thread at a time.