Recursive Name Search - java

i want to find a name in a recursivly build itemlist.
Items can have subitems which can have subsubitems etc.
For the first level it worked. for deeper levels the correctly found name/id mapping gets an overwrite from the stack. Because of the string result, i have to write the return statement at the end. So i have a mental blockage how i can solve this problem. I appreciate for your help.
public String getNameForID(List<Item> top, long id, String name ) {
for (Item i : top) {
if (i.getId() == id) {
name = i.getName();
return name;
}else{
this.getNameForID(i.getSubItemsList(), id,name);
}
}
return name;
}

This must be what you're looking for:
public String getNameById(List<Item> items, long id) {
// boundary condition
if (items == null || items.isEmpty()) {
return null;
}
// looping
for (Item item : items) {
// if current is
if (item.getId() == id) {
return item.getName();
}
// recursion
String name = getNameById(item.getSubItemsList(), id);
// if nested found
if (name != null) {
return name;
}
}
// boundary condition
return null;
}

Your recursive call to getNameForID must also be able to return a value. It also needs to be able to indicate that no value was found so that the recursion is terminated.
Based on #sp00m's previously deleted (and slightly incorrect) answer, try this:
public String getNameById(List<Item> items, long id) {
// sanity checking conditions to terminate recursion early
if (items == null || items.isEmpty()) {
return null;
}
// iterate over collection
for (Item item: items) {
if (item.getId() == id) {
return item.getName();
} else {
String name = getNameById(item.getSubItemsList(), id);
if (name != null) {
return name;
}
}
}
// final termination condition - entry wasn't in this list
return null;
}

you do not assign the value returned here to name:
this.getNameForID(i.getSubItemsList(), id,name);
actually you don't need the parameter name - just return name or null in each call

Related

How to avoid many if-else statements

I have a class like this..
Class A {
public void someNullCheckingMethod(Student stu) {
if (stu.getName() != null) {
String name = stu.getName();
} else {
// get name from other source(its something like
// fallback)
}
if (stu.getId() != null) {
String id = stu.getId();
} else {
// get id from other source(its something like
// fallback)
}
if (stu.getAddress() != null) {
String address = stu.getAddress();
} else {
// get address from other source(its something like
// fallback)
}
if (stu.getCity() != null) {
String city = stu.getCity();
} else {
// get city from other source(its something like
// fallback)
}
if (stu.getGender() != null) {
String gender = stu.getGender();
} else {
// get gender from other source(its something like
// fallback))
}
}
}
is there a way to avoid too many if statements? As you can see here I am checking null condition for each property but i don't want many checks to get desired result just want to reduce if conditions as well as want to get same desired result whatever I will get by putting all these if conditions.
Since you don't provide any context there's a few things you can do based on some assumptions.
Assumption one:
if the values are initialized as null
String name;
// or
String name = null;
Then you can just assign the values and ignore if the fields are null or not since the class members are null already.
String name = stu.getName(); // String name = "Some Name" OR null, depending on return value of method
Assumption two:
If you just want to avoid the if statements you can go with ternary operators
String name = stu.getName() != null ? stu.getName() : null; // Or some other default value
There are a few other methods that pops into my mind as well but without more context they are a bit useless at this point.
You could at least reduce the "verbosity" with Optional.
String name;
if (stu.getName() != null) {
name = stu.getName();
} else {
name = "default"
}
Would become
String name = Optional.ofNullable(stu.getName()).orElse("default");
Th choice is yours to return an Optional directly from the POJO Student for any value that could be null.
This would give a cleaner solution :
String name = stu.getName().orElse("default");
If getName looks like :
public Optional<String> getName(){
return Optional.ofNullable(name);
}
If using an external library is an option, then you should take a look at Dozer or MapStruct.

My linked list isn't returning the proper values or updating a list properly

When my program comes to this method it never seems to update the target value. If I input "dave" it will remain "dave" no matter how many calls to the method are made.
public Person lookup(String name){
if(firstPerson == null){
return null;
}
Person target = null;
for (target = firstPerson; target != null; target = target.nextPerson){
if(name.equals(target.name)){
return target;
}
else {
return null;
}
}
return target; // replace this line
}
If I add a friend via this addFriend method firstFriend will end up printing whatever the last added name was. If the inputted named were rob bill and travis
The output would be travis travis travis.
public void addFriend(Person friend){
firstFriend = new Friend(friend, firstFriend);
return; // replace this line
public String friendString(){
String friendList = "";
if(firstFriend == null){
return null;
}
for(Friend pointer = firstFriend; pointer != null; pointer = pointer.nextFriend){
friendList = friendList + firstFriend.who.name + " ";
}
return friendList.trim(); // replace this line
}
You always return in the first iteration of the loop. If the person is found it's returned (the if branch), and if it isn't, null is returned (the else branch). Instead, you should keep iterating until you find the correct person or exhaust the list. The first condition, BTW, is a subset of the loop (if firstPerson is null target will just become null immediately), and can (should!) also be removed:
public Person lookup(String name){
Person target = null;
for (target = firstPerson; target != null; target = target.nextPerson) {
if (name.equals(target.name)) {
return target;
}
}
return target; // Or null explicitly - matter of taste.
}
if(name.equals(target.name)){
return target;
}
else {
return null;
}
The else part needs to go away. The effect of this code is that it only checks the first value and if it is not the value that you want to look up it is coming out straight away.
Change
return target; // replace this line
to return null;
and remove the else part mentioned above

Using 'contains' method in a class array

I have a class like this:
public static class TiposDeHistorial
{
String CODIGO, TIPO;
public TiposDeHistorial()
{
}
public String getCODIGO()
{
return CODIGO;
}
public void setCODIGO(String CODIGO)
{
this.CODIGO = CODIGO;
}
public String getTIPO()
{
return TIPO;
}
public void setTIPO(String TIPO)
{
this.TIPO = TIPO;
}
}
and a list of it:
ArrayList<TiposDeHistorial> tiposHistorial;
So my question is: can I use tiposHistorial.contains(...) to search in a specific array field, CODIGO or TIPO, for example?
First of, you do not have an array but an ArrayList.
The contains method on a List operates with the equals method of it's stored elements (TiposDeHistorial in your case). Therefore the answer to your question is no.
Trying something like tiposHistorial.contains("a") will not work as there is a type mismatch: your list is of type TiposDeHistorial while you try to check for an element of String.
If you are using Java 8 you can use following code:
tiposHistorial.stream()
.filter(x -> "specific value for CODIGO".equals(x.getCODIGO()))
.findFirst()
.orElse(null);
It will return TiposDeHistorial object in the list containing specific CODIGO value or null otherwise.
As for your question: "contains" method just returns "true" or "false", not an object. Moreover it uses "equals" method of your object, so it will not help if you want to search using fields.
Contains method will return true only if your object equals with ur list elements objects.
You can try extending equals method and have your own criteria which can work for either CODIGO or TIPO.
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
test other = (test) obj;
if (CODIGO == null) {
if (other.CODIGO != null)
return false;
} else if (!CODIGO.equals(other.CODIGO))
return false;
return true;
}
The answers already given here are all correct, just if You don't know java streams, and would like to check if the list contains both some CODIGO and TIPO fields, for me the simplest solution would be:
ArrayList<TiposDeHistorial> tiposHistorial = new ArrayList<>();
//add elements to the list
String tipo = "TIPO"; // the TIPO value You are looking for in the list
String codigo = "CODIGO"; // the CODIGO value You are looking for in the list
boolean containsTipo = false;
boolean containsCodigo = false;
for (TiposDeHistorial element: tiposHistorial) {
if (!containsTipo && element.getTIPO().equals(tipo)) {
containsTipo = true;
}
if (!containsCodigo && element.getCODIGO().equals(codigo) ){
containsCodigo = true;
}
if (containsTipo && containsCodigo)
break;
}
By editing it just a bit, You may also find which elements of the array contain the values You are looking for, if that will be Your intention

How to break out and return an object from a recursion after meeting a certain condition is met

I have a recusrion function where i want to return the object as soon as certain condition is met . The function looks like this .
GroupNavigationItemSRO getCategorySpecificNavItem(List<GroupNavigationItemSRO> items,String url) {
GroupNavigationItemSRO sro = new GroupNavigationItemSRO();
if(items != null && !items.isEmpty()){
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else
getCategorySpecificNavItem(item.getChildren(),url);
}
}
return null;
}
Now the function returns null and i get why its happening despite meeting the criteria .How to avoid that and end the recursion as soon as the url is found.
What you want to do is stop looking when you've found it, but recurse until you do.
The main problem with your existing code is that the recursive call's return value is ignored. Instead, you want to look at that return value and, if it's not null, return it; you're done:
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else {
GroupNavigationItemSRO itemFromChild = getCategorySpecificNavItem(item.getChildren(),url);
if (itemFromChild != null) {
// Found!
return itemFromChild;
}
}
}

java.util.NoSuchElementException using iterator in java

I'm trying to iterate through a list using the iterator over my list of Logs. The goal is to search for a logs which contains the same phonenumber, type and date as the new log
However, I get a java.util.NoSuchElementException in my conditional statement. Does anyone know what might cause the problem?
My code
public void addLog(String phonenumber, String type, long date, int incoming, int outgoing)
{
//Check if log exists or else create it.
Log newLog = new Log(phonenumber, type, date, incoming, outgoing);
//Log exists
Boolean notExist = false;
//Iterator loop
Iterator<Log> iterator = logs.iterator();
while (iterator.hasNext())
{
//This is where get the exception
if (iterator.next().getPhonenumber() == phonenumber && iterator.next().getType() == type && iterator.next().getDate() == date)
{
updateLog(newLog, iterator.next().getId());
}
else
{
notExist = true;
}
}
if (notExist)
{
logs.add(newLog);
}
}
You are calling next() a bunch of times in one iteration forcing the Iterator to move to an element that doesn't exist.
Instead of
if (iterator.next().getPhonenumber() == phonenumber && iterator.next().getType() == type && iterator.next().getDate() == date)
{
updateLog(newLog, iterator.next().getId());
...
Use
Log log = iterator.next();
if (log.getPhonenumber() == phonenumber && log.getType() == type && log.getDate() == date)
{
updateLog(newLog, log .getId());
...
Every time you call Iterator#next(), it moves the underlying cursor forward.

Categories

Resources