2

I made a post earlier about a similar topic. However, I thought I would clarify something and change my question.

So this project I am doing is confusing me. I am only 5 weeks in and the question is asking me to create a method that returns a title of a photo in an array of photos. each photo has a title. This is the code:

public class Album {

    private String albumtitle;
    private ArrayList<Photo> photos;

    /**
     * This constructor should initialize the
     * instance variables of the class.
     */
    public Album(String title) {

        this.albumtitle = title;
        photos = new ArrayList<>();

}

/** When passed a title, this method should
     * return the first Photo object in the album with
     * a matching title. If there is no such object, it 
     * should return null.
     * 
     * @param title A title to search for
     * @return A Photo object, or null
     */
    public Photo searchByTitle(String title) {

        //TODO enter code here
        }

    }

Now, my lecturer said not to use for loops as the project is from chapter 1 to 4 (chapter 5 is for loops/iterations)

https://lms.uwa.edu.au/bbcswebdav/pid-1134902-dt-content-rid-16529804_1/courses/CITS1001_SEM-2_2018/lectures/BooksReadJournal.java.pdf

This is an example of what the lecturer did with a program about books without using for loops. However, notice it has (int index) as a parameter and then uses String title = bookTitles.get(index)

My point is, how do I do it without using for loop? I don't want them to feel as I have copied off the internet something we haven't learned.

Thanks,

12
  • 1
    The link you provided brings us to a page wherre we have to input some credential. Commented Aug 31, 2018 at 12:12
  • 1
    Learn about recursive calls. Those are not loops but this will do it. (now, I let you search and try this since you didn't even tried using a loop) Commented Aug 31, 2018 at 12:13
  • 3
    Are you allowed to use a "while" loop instead? Outside using a Map<> instead of a ArrayList, you have me stumped. Commented Aug 31, 2018 at 12:15
  • 3
    @AxelH good idea, but if they haven't taught loops yet, I doubt the professor is expecting them to understand recursion. Commented Aug 31, 2018 at 12:15
  • 2
    Can you give us the "title" of the 4 chapter ? Since you are limited to only what you know, we need to know what we can't use. Seems you already know about class but don't know yet about loop, that doesn't seems right. @christopher this means to implement equals properly too. Commented Aug 31, 2018 at 12:17

7 Answers 7

3

If you are limited to avoid use the for-loop and use the if-else only, the recursive call is an alternative:

public Photo searchByTitle(String title) {
    return searchByIndex(title, 0); 
}

private Photo searchByIndex(String title, int index) {
    if (index < photos.size()) {                       // Has next? If yes ...
        Photo next = photos.get(index);                //   Get next
        if (!title.equals(next.getPhotoName())) {      //   Does the title match? If not...
            return searchByIndex(title, ++index);      //      Check the next one
        } else return next;                            //   Otherwise you found it
    } return null;                                     // ... if no next, return null
}

I assume the Photo class has a field String photoName accessible with a getter which is about to be compared with the String title.

Sign up to request clarification or add additional context in comments.

4 Comments

@AxelH: The header explains the problem at all: "Finding an element in an Array using ONLY If statement".
@AxelH: I always miss the title which gives the crucial info :D
@Nikolas I don't think the task is solveable using ONLY if/else. Unless you have a fixed size list and check all indexes. And actually the question explains that he is not allowed to use for loops. Nothing about recursion being forbidden.
@jokster: It's NOT solvable using ONLY if/else itself. I chose a solution composed with the low-level construct such as recursion rather than risking that the Comparable, Iterator and Stream would be forbidden. I use that language offers itself, not what the other implementations offer.
2
  1. Implement Comparable on Photo that returns true if the title is the same.
  2. Construct a temporary Photo object with the given type.
  3. Leverage the indexOf method on ArrayList to find index of Album with the Photo title.
  4. Use get(int) to get the Album.

4 Comments

This doesn't answer what OP wants: using ONLY If statement.
Using Comparable violates the condition using ONLY If statement.
@AxelH: According to your logic, I can use Stream-API: photos.stream().filter(photo -> title.equals(photo)).findFirst().orElse(null);. The same goes for Iterator and Comparator. The requirement is to stick with the low-level solution using if-else statements. I doubt you find any of those interfaces listed in the chapters 1-4 as OP mentioned in his link to book.
I think the "use only if statement" means not using loops, not that ALL statements need to be "ifs"... Since you know, thats not possible to do, at least you will have statements inside the "ifs" which arent "ifs"
1

I've implemented the code from the comments above.
The idea here is to build a temporary object in the searchByTitle method and passing it to the List.indexOf method having the Photo class that overrides Object.equals.

public class Album {

    class Photo {
        private String title;

        public Photo(String title) {
            this.title = title;
        }

        public String getTitle() {
            return title;
        }

        @Override
        public boolean equals(Object anObject) {
            return title.equals(((Photo)anObject).getTitle());
        }
    }

    private String albumtitle;
    private ArrayList<Photo> photos;

    /**
     * This constructor should initialize the
     * instance variables of the class.
     */
    public Album(String title) {
        this.albumtitle = title;
        photos = new ArrayList<>();
    }

    /** When passed a title, this method should
     * return the first Photo object in the album with
     * a matching title. If there is no such object, it 
     * should return null.
     * 
     * @param title A title to search for
     * @return A Photo object, or null
     */
    public Photo searchByTitle(String title) {
        Photo tmp = new Photo(title);
        int index = photos.indexOf(tmp);
        if (index >= 0)
            return photos.get(index);
        return null;
    }

}

This is a very basical implementation of equals which doesn't take into account null argument and its type.

Comments

0

You can bring another ArrayList of String which keeps names of photo titles. Then in search function search with photo title in String arrayList. If find an index then return the Photo object of that index from photoTitles, as you are inserting in both arrayList in same order.

public class Album {

    private String albumtitle;
    private ArrayList<Photo> photos;
    private ArrayList<String> photoTitles;


    public Album(String title) {

        this.albumtitle = title;
        photos = new ArrayList<>();
        photoTitles = new ArrayList<>();
    }

    public Photo searchByTitle(String title) {

        int index = photoTitles.indexOf(title);
        if(index >= 0) {
            return photos.get(index);
        }
        return null;
    }
}

5 Comments

++ I think this is the best solution so far
Definitely a big no for me. If I edit the title of one photo, your solution become useless because the second list don't match anymore. Duplicate value isn't a good idea.
If you edit a photo title, why not you edit in arrayList too? If you go with this design you should do this too. @AxelH
Because I don't know from outside of Album that searchByTitle returning the instance needs another list, and since I retrieve the instance, I am free to do whatever I want with it. Like album.searchByTitle(oldTitle).setTitle(newTitle). You are hiding complexity here that will blow in the face of the next developer.
got your point. I didn't think that deeper as it is only a course project.
0

Just because I like the recursion idea but using it with an index search on a List is not optimal, let's use an iterator instead. The recursive method will simply check if there is one value to take, check and call again until we find the value or reach the end.

//Just hide the used of an iterator
public static Photo getFirstWithTitle(List<Photo> list, String value){
    return getFirstWithTitle(list.iterator(), value);
}

//recursive method
private static Photo getFirstWithTitle(Iterator<Photo> it, String value){
    if(it.hasNext()){ 
        Photo p = it.next();
        return p.getTitle().equals(value)?
            p
            : getFirstWithTitle(it, value);
    } else
        return null;
}

4 Comments

really a ternary with a fixed boolean value for one side? Actually this can be collapsed to return it.hasNext() && (it.next().equals(value) || contains(it, value));
@jokster: That's correct since if it.hasNext() is false, the rest won't be evaluated.
@AxelH looks different now. And now the if and ternary make sense the way they are. Original was ... ? true : ...
@jokster Well this is my original code (written in an IDE) but during the redaction of the answer, I thought this was maybe to much "solution" given so I changed getFirstWithTitle into contains ... giving the previous version... I didn't checked if it was "smart" at that point...
-1

You can use built in binarySearch and a comparator. Probably the most elegant way and how I usually do it

public Photo searchByTitle(String title) {
    Photo item = null
    Comparator<Photo> comparator = new Comparator<Photo>() {
        public int compare(Photo it1, Photo it2) {
            return it1.getTitle().compareTo(it2.getTitle());
        }
    };
    Collections.sort(photos, comparator); //This should go after you set the items, ie. you sort it once
    int index = Collections.binarySearch(photos, comparator);

    if (index >= 0) {
        item = photos.get(index);
    }
    return item
}

5 Comments

You can use lambda: Comparator<Photo> comparator = (it1, it2) -> it1.getTitle().compareTo(it2.getTitle());. The usage of Comparator and Collections.sort() seems fine, yet the OP states: using ONLY If statement. Otherwise I'd answer with: photos.stream().filter(photo -> title.equals(photo)).findFirst().orElse(null);.
You can use many things, lambdas add nothing to it not to mention not cross platform
And how exactly would you ensure that a binary search finds the first match instead of any match?
Also the sort has a complexity of O(n log(n)) which is less efficient than just iterating over the list with complexity of O(n)
Nobody cares about complexity, the question was to find an item without if statements? And nobody mentioned that about ordering or multiple items etc. The question was "to find the first photo which matches the title". This can be any photo which matches the title.
-2

Using Java you don't even need a 'if' statement. This can be achieved through this:

public Photo searchByTitle(String title) {

    return photos.stream().filter(photo -> title.
            equals(photo.getTitle())).findAny().get();      
}

p.s: I did not have access to your enunciate question (the link provided)

7 Comments

This doesn't answer what OP wants: using ONLY If statement.
Actually I didn't have access to the material, may be he doesn't know that Java provides more than if else statements. Recursion doesn't seem to be a good idea to simple problem like that.
Neither do I :)) It's correct to mention that there are the way better approaches as you have provided. However, the header of question states: using ONLY If statement - we can only guess a reason behind the OP's decision. We can aim him, but not amend the question itself.
The problem is that if he didn't have access to loop structures at the class, will he able to implement complex solutions instead of using native programming language resources?
@AdemirConstantino findAny() is not required to return the first occurence and get() throws a NoSuchElementException instead of returning null. The question asks to return the first Photo object or null if there is no such one.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.