-2

If we have a class that looks like this:

public class Item {
    public Item(String itemId, String description) {
        this.itemId = itemId;
        this.description = description;
    }

    private final String itemId;
    private final String description;

    public String getItemId() {
        return this.itemId;
    }

    public String getDescription() {
        return this.description;
    }
}

And I have a Collection of those objects

Collection<Item> items = FXCollections.observableArrayList();

And now I want to pull from the collection, the Item that has a specific itemId ...

How can I do that without iterating through the Collection so that I can have a method that looks like this:

//pseudocode
public Item getItem(String itemId) {
    return Item from Collection with itemId == itemId; 
}

Instead of this

public Item getItem(String itemId) {
    for(Item item : items) {
        if (item.getItemId().equals(itemId)) return item;
    }
    return null;
}
Michael Sims
  • 2,360
  • 1
  • 16
  • 29
  • 3
    By storing the data as a Map instead of a generic collection and have the itemId as the key of the map. On a generic collection or list this is not possible. – luk2302 Nov 24 '21 at 08:13
  • I know I could use a map, but I wanted to avoid using a map in this situation ... is there no way to do this? – Michael Sims Nov 24 '21 at 08:15
  • 1
    You need to index your collection by an arbitrary value. There’s a name for that … it’s called a `Map`. – Boris the Spider Nov 24 '21 at 08:17
  • @MichaelSims why would you want to avoid using a map? If you don't, each time you search for an item you will have to loop through elements. If you do, you'll enjoy the power of hashes. – Matteo NNZ Nov 24 '21 at 08:17
  • @ScaryWombat that’s just a linear search under the hood though. – Boris the Spider Nov 24 '21 at 08:18
  • @ScaryWombat if you think about it, without a hashtable, how else would it work? – Boris the Spider Nov 24 '21 at 08:20
  • I was just asking if Java had a way to do this with the Collections class ... if the answer is NO, then the answer is NO ... that's all I'm looking for. – Michael Sims Nov 24 '21 at 08:23
  • 1
    @MichaelSims in all languages (not only Java) you can have collections of elements and loop through them to search what you need. But if the research is always done against a specific key, then Maps is better because the research is much faster. – Matteo NNZ Nov 24 '21 at 08:27
  • No language can have a non-indexed data structure which has key-based access without a loop because those simply contradict each other. You want key-based access explicitly without allowing key-based data structure. That does not work. – luk2302 Nov 24 '21 at 08:32
  • @luk2302 - And what I'm looking for ... is if there is a way to loop through the collection and return the result in a single line of code. – Michael Sims Nov 24 '21 at 08:34
  • `for(Item item : items) {if (item.getItemId().equals(itemId)) return item;}return null;` - single line. – luk2302 Nov 24 '21 at 08:35
  • @luk2302 - not a single line of code (multiple ; ) – Michael Sims Nov 24 '21 at 08:36
  • Note that this is the first time you mention anything related to line count - which is nonsense requirement anyway. So far you required "without iterating through the Collection" which is not possible. – luk2302 Nov 24 '21 at 08:36
  • No, that is a single line, your entire program can be in a single line (I just took your last snippet and removed the newlines) – luk2302 Nov 24 '21 at 08:37
  • @luk2302 Perhaps I should modify the question to say: without MANUALLY iterating through the Collection? – Michael Sims Nov 24 '21 at 08:37
  • Is the posted answer iterating manually or not? What does "manually" mean in your context? – luk2302 Nov 24 '21 at 08:38
  • @luk2302 Yes, I know what you did, but it was an asinine response. I'm not an idiot. – Michael Sims Nov 24 '21 at 08:38
  • @luk2302 If you cannot understand what I'm asking for based on my question, then just ignore this post or tell me how my question is ambiguous and I'll correct it. – Michael Sims Nov 24 '21 at 08:40
  • *"How can I do that without iterating through the Collection"* - you cannot. As we told you multiple times already. But your requirements change every few minutes, between not iterating, not iterating "manually", being a single line, being a single statement, ... – luk2302 Nov 24 '21 at 08:42
  • @luk2302 Consider when developers boast about how many lines of code their programs are ... they don't say ONE ... because each line of code has a way of being deciphered. Java uses the semicolon. – Michael Sims Nov 24 '21 at 08:44
  • @luk2302 I give two examples ... one is the example of what I'm looking for and the other is the example that I DO NOT want to do ... which is iterating through the Collection. What is it about my question that confuses you? – Michael Sims Nov 24 '21 at 08:45
  • @luk2302 - the question has been answered and obviously IT IS possible to do what I'm trying to do here. – Michael Sims Nov 24 '21 at 08:52
  • @luk2302 Just to be precise, you asked "without iterating through the collection". The answer given does iterate through the collection, just it's not you doing it but the stream API. So no, the answer is "IT IS NOT" possible ;) – Matteo NNZ Nov 24 '21 at 09:33

1 Answers1

2
return items.stream().filter(i->i.getItemId().equals(itemId)).findFirst().get();
Serge Iroshnikov
  • 749
  • 1
  • 6
  • 17
  • Correct, but for each research you'll have to loop through all the elements until you find the first one... Maps are there exactly to optimize this kind of use case. – Matteo NNZ Nov 24 '21 at 08:27
  • However, it will be linear search anyway. For long lists, it is better to use maps as indexes – Serge Iroshnikov Nov 24 '21 at 08:29
  • 1
    @MatteoNNZ, I agree. But the guys asked about more declarative way of doing his linear search. He did not ask how to optimize it. – Serge Iroshnikov Nov 24 '21 at 08:32
  • @SergeIroshnikov Matteno NNZ gave me exactly what I was looking for. – Michael Sims Nov 24 '21 at 08:49
  • @MichaelSims don't misunderstand me. Serge's answer works, and responds to your "need" of having a single statement. What I'm trying to tell you is that even if Java stream API allows you to loop through elements in a single-line, it's not the right way to do it. Having the code in one statement rather than 10 changes nothing to performance. On the other hand, if your collection contains 20 millions elements and your index happens to be at the end, this solution will take way longer than using a Map since the beginning. If you want to write clean code, it's a map you should use, trust me. – Matteo NNZ Nov 24 '21 at 09:25
  • Behind the scenes, the stream does exactly what you were doing at the beginning. Your code will look "more beautiful", but not the right approach. But if after all it's just esthetic you're looking for, then sure go for it. We're simply trying to suggest you the right way :) Have a good day – Matteo NNZ Nov 24 '21 at 09:29
  • @MatteoNNZ - in this specific use case, there will be less than 10 elements to loop through, but I will make note of the fact that using this method is no more efficient than it is to use a few more lines of code and loop through the collection "manually". I realize that because the collection is not mapped, there is technically no way to go straight to the element I'm seeking and in the case where there are significantly more elements to address, a Map would certainly be the best choice, at least that is how I understand the situation to be. – Michael Sims Nov 30 '21 at 04:09
  • @MatteoNNZ - you nailed it ... I was trying to reduce the overall appearance of a method that was getting a little out of control in terms of looking ... cluttered. – Michael Sims Nov 30 '21 at 04:10