Checking that at least Value in HashMap matches? - java

I am trying to figure out how to iterate through my HashMap to see if at least one Value in it matches what I am looking for.
for(int i=0; i<allDogsInkennels.size(); i++){
Map<String, DogStatus> allDogsStatus = allDogsInKennels.get(i).getAllStatuses();
}
How can I add an If statement / loop here to check that at least one of the statuses matches e.g. "APPROVED".
Note: String= the Dogs Id
,DogStatus= Enum showing dog's status

if (allDogsStatus.containsValue(DogStatus.APPROVED)) {
// ...
}

You can iterate over the map and stop if you hit a match:
boolean found = false;
for (DogStatus value : allDogsStatus.values()) {
if (value == DogStatus.APPROVED) {
found = true;
break;
}
}
Even better is to refactor the above into a function that return the boolean.
Edit: I feel dumb for not remembering the containsValue method. That's probably the best approach, even though complexity is the same.

Related

Convert cycle to lambda expression

List<Mt4Strategy> openStrategies = ...
OrderType sample = openStrategies.get(0).calculate().getOrderType();
boolean success = true;
for (int i = 1; i < openStrategies.size(); i++) {
Mt4Action calculate = openStrategies.get(i).calculate();
if (calculate.getOrderType() != sample) {
success = false;
break;
}
}
OrderType is an enum.
I don't know what the first element contains and as a result am forced to make openStrategies.get(0).... I want to get rid of this get(0), but how?
I tried to use lambda like this:
OrderType sample = openStrategies.get(0).calculate().getOrderType();
boolean success = IntStream.range(1, openStrategies.size()).mapToObj(i ->
openStrategies.get(i).calculate()).noneMatch(calculate ->
calculate.getOrderType() != sample);
It's a good start but does not resolve my get(0).
Can using a lambda get rid of it? How I can write this to check success without get(0)? Lambda solution in priority something similar to last case .noneMatch.
You apparently want to determine whether all the input list elements have the same order type. A stream ought to make this pretty simple. For example,
boolean success = openStrategies.stream()
.map(s -> s.calculate().getOrderType())
.distinct()
.limit(2)
.count() == 1;
Note here the distinctness comparisons are done with equals rather than ==. If you really need ==, it's more difficult.
This checks for exactly one value in the list. If the input can be empty and you want the result to be true in that case, change == 1 to <= 1.
The limit(2) isn't needed for correctness but allows the search to stop as soon as a second distinct value is found, so it's more efficient.
There are other ways to do this.
Responding to comment
There are various hacky ways you could get the common value without calling .get(0), but none that would be clearer (at least that I can think of). It's silly to code things in oddball ways just to avoid a call you don't like the looks of.

Fetch value from a set object in java

I'm iterating a set object to find a particular value. Is there any short way to fetch instead of iterating it? Here is my code
for(Tree t : assignedTrees) {
println t.treeName;
}
The above code will return the expected value.
assignedTrees is the set object
Set<Tree> assignedTrees = new HashSet<Tree>()
println assignedTrees will return
[Tree{id=null, treeName=Mango}]
Can I fetch the treeName instead of iterating?
You can fetch an object from a set by calling mySet.get(object). However, in your case you wish to fetch an object based on one of its attributes. The best way to do this is with a map - e.g.
Map<String, Tree> trees = new HashMap<>();
trees.put(treeObject.treeName, treeObject);
Tree myTree = trees.get("myTreeName");
Note that if you're putting your own objects into sets or maps, you must override the equals and hashcode methods, or very strange things will happen.
In general you can use lambda to find any/first element that fullfils any condition. For example:
Set<Integer> coolStrings = new HashSet<String>();
coolStrings.add("HEHE")
coolStrings.add("NOPE")
coolStrings.add("JP2GMD")
coolStrings.add("1234")
try{
String nice =
coolStrings.stream().filter(
(str) -> { return str.equals("JP2GMD") ||
str.equals("2137"); }
}).findFirst().get();
)
System.out.println("Yay, i found a REALLY cool string! : " + nice);
}
catch(NoSuchElementException e){
System.out.println("Not even one awesome string was found :(");
}
It will print "JP2GMD"
(I didn't compile it, there might be some minor syntax errors)
Working with Stream class is extremally handy (as for java standards)

Updating method to remove loop

This is how I understand method getUser below :
Return a User object or null
Get a Set of users and assign them to userSer.
If the set is not empty begin iterating over the set but
return the first user within the set.
Here is the method :
private User getUser(UserDet arg)
{
Set<User> userSet = arg.getUsers(User.class);
if (CollectionUtils.isNotEmpty(userSet))
{
for (User user : userSet)
{
return user;
}
}
return null;
}
I think I could replace the method with this :
private User getUser(UserDet arg)
{
Set<User> userSet = arg.getUsers(User.class);
if (CollectionUtils.isNotEmpty(userSet))
{
return userSet.iterator().next();
}
else {
return null;
}
}
This new method removes the loop and just returns the first element in the set, same as original implemention. Is it correct?
Yes. Actually, it's pretty much almost the same thing, as a foreach loop is syntactic sugar for using an iterator from an Iterable.
Note, however, that you don't need the nonempty check in the first variant, since the loop won't iterate in the case of an empty set anyway.
yes both are same. in first implementation, control will return on first iteration of the loop from the function and consequently loop will end.
Yes it is correct, I'd even go for removing the CollectionUtils.isNotEmptySet and use the Iterator's hasNext method... If the set is guaranteed to be non-null.
It seems to be correct, but it will only make the method a bit easier to read, it will not optimize it in terms of performance. Still I think the change is good and you should do it.
Yes, it does pretty much the same, but if your spec says to start iterating then maybe you should - maybe this method will be extended in the future.
BTW: it is a good convention that your method has only one return statement (i.e. you can create a variable, which will be returned, assigned a null at the beginning and assign a user inside your loop)
Yes. Both the methods return the first element in the set. The first method seems to have been written for something else previously and changed then keeping the for loop intact.
In anycase, the second method that you're proposing won't give any significant performance benefit but should be a better way than the first one.
So in case, UserDet#getUsers(Class) never returns null (but an empty Set in case no user could be found), the shortest (and in my opinion most readable) form is:
private User getUser(UserDet arg) {
Set<User> userSet = arg.getUsers(User.class);
return userSet.isEmpty() ? null : userSet.iterator().next();
}
I would do this.
I won't run a loop and more over I'l add a null check.
private User getUser(UserDet arg) {
Set<User> userSet = arg.getUsers(User.class);
if (userSet != null && userSet.size() > 0) {
return userSet.iterator().next();
}
return null;
}

Iterating over a collection in Java (for a C++ programmer)

I am attempting to write code to traverse a collection of type InstallationComponentSetup:
java.util.Collection<InstallationComponentSetup> components= context.getInstallationComponents();
Iterator it = components.iterator();
while (it.hasNext())
{
if (((InstallationComponentSetup)it).getName() == "ACQ")
{
return true;
}
}
The cast in the if-statement fails, but I don't really know why (I am a C++ programmer!).
If someone could give me some pointers as to what I am doing wrong I would be grateful.
it is an Iterator, whereas it.next() is an InstallationComponentSetup.
The error results from the fact that an Iterator cannot be cast as an InstallationComponentSetup.
Also, you shouldn't even need to cast if you parametrize the Iterator appropriately:
Iterator<InstallationComponentSetup> it = components.iterator();
Finally, don't compare strings with something like a == b, instead use a.equals(b). See "How do I compare strings in Java" for further details.
You might also want to look into the for-each loop if all you want to do is iterate over the collection. Your code can be rewritten as:
for (InstallationComponentSetup component : components)
if (component.getName().equals("ACQ"))
return true;
If you are comparing String , use equals() method .
Even your casting is wrong.You have to invoke next() on the iterator to get the next element . Hence it.next() gives you the next element which will be an object of InstallationComponentSetup, it is not of type InstallationComponentSetup hence the cast will fail.
Here you are casting the Iterator to your class type which will fail.
if (((InstallationComponentSetup)it).getName() == "ACQ")
{
return true;
}
I believe there is no need of cast here as you have defined the Collection to hold the specific type of element and also if you declare the Iterator of a specific type.
You can simply do :
// define Iterator of InstallationComponentSetup
Iterator<InstallationComponentSetup> it = components.iterator();
if("ACQ".equals(it.next().getName())) {
return true;
}
You can also consider using the enhanced for loop in Java , if your purpose is only to read the elements .
for(InstallationComponentSetup component: components) {
if("ACQ".equals(component.getName())) {
return true;
}
}
You have to retrieve the next element in the iteration before you compare:
InstallationComponentSetup next = it.next();
if (next.getName() == "ACQ")
{
return true;
}
Try to use the following code. It is more concise and easier to understand.
Collection<InstallationComponentSetup> components= context.getInstallationComponents();
for(InstallationComponentSetup comp : components){
if("ACQ".equals(comp.getName()){
return;
}
}
I think you had two problems in you code.
Cast the iterator to an object doesn't work like that. You need to use it.next() to get the object and move the iterator.
like already mentioned you need equals to compare Strings. == compares "memory locations" (in C++ terms).
Use it.next() to get the next element.
Also, use the .equals() method to compare strings in Java. Otherwise, the references are compared.
Finally, the cast should be unnecessary with a type-parameterized Iterator.
while (it.hasNext())
{
if ( it.next().getName().equals("ACQ") ) {
...
}
}
You have to retrieve the next element in the iteration before you compare:
java.util.Collection<InstallationComponentSetup> components= context.getInstallationComponents();
Iterator<InstallationComponentSetup> it = components.iterator();
while (it.hasNext()) {
if ("ACQ".equals(it.next().getName())) {
return true;
}
}
It would be easier to use foreach loop, make use of generic type, use equals for String and change string comparison order to be null secure.
Collection<InstallationComponentSetup> components= context.getInstallationComponents();
for (InstallationComponentSetup setup : components)
{
if ("ACQ".equals(setup.getName()))
{
return true;
}
}
The install4j API is still for Java 1.4, so there are no generics yet. This will work:
for (Object o : context.getInstallationComponents()) {
InstallationComponentSetup component = (InstallationComponentSetup)o;
if (component.getName().equals("ACQ")) {
return true;
}
}

How to compare group of Strings

I have the following code..
WorkPackage spack=(WorkPackage)primaryBusinessObject;
WTSet res;
WTPart spart=null;
String state=null;
res=wt.facade.persistedcollection.PersistedCollectionHelper.service.getAllMembers(spack);
System.out.println("the values are "+res);
java.util.Iterator iter=res.persistableIterator();
while(iter.hasNext())
{
spart=(wt.part.WTPart) iter.next();
wt.lifecycle.LifeCycleState st=spart.getState();
String state=st.toString(); //Lifecycle state of part object
}
if(state.contains("APPROVED"))
result="Proceed";
In the above code I'm passing a windchill package and it may have muliple number of WTPart objects.Each part may have different life cycle states.What I want is if every part state is "APPROVED" means it should proceed in my workflow.
For eg.
LifeCycle states of
Part1=IN WORK
Part2=IN REVIEW
Part3=APPROVED
Part4=APPROVED
Part5=CANCELED
I want to compare all the objects from my package is APPROVED I can store these in vector or a arraylist and I don't know how to compare all the objects from that.My above code will pass if any one of objects state is APPROVED.I know this question not related to windchill.Somebody help me out of it
If you store all of the states in an ArrayList<String> states then you can test if they are all APPROVED using something like:
boolean allApproved = true;
for(int i = 0; i < states.size(); i++) {
if(!states.get(i).equals("APPROVED") {
allApproved = false;
}
}
At the end of the for loop, if allApproved is still true, you're good to go.

Categories

Resources