59

I'm working on creating a calculator. I put my buttons in a HashMap collection and when I want to add them to my class, which extends JPanel, I don't know how can I get the buttons from my collection. So I found on the internet the 2 last lines of my code, but I don't know their meaning.

Here is my code:

import java.awt.Component;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JPanel;


public class PanneauCalcul extends JPanel {

    private HashMap<String, JButton> listbouton = new HashMap<String, JButton>() ;

    public PanneauCalcul() {
        for(int i = 0; i < 10; i ++) {
            listbouton.put("num" + i, new JButton("" + i)) ;
        }

        listbouton.put("add", new JButton("+")) ;
        listbouton.put("soustract", new JButton("-")) ;
        listbouton.put("multiply", new JButton("x")) ;
        listbouton.put("divise", new JButton("/")) ;
        listbouton.put("equal", new JButton("=")) ;

        Set entrys = listbouton.entrySet() ;

        Iterator iter = entrys.iterator() ;

        while(iter.hasNext()) {
            Map.Entry me = (Map.Entry)iter.next();  //don't understand 
            this.add((Component) me.getValue()) ;   //don't understand
        }

        EcouteCalcul ecout = new EcouteCalcul(this) ;
    }
}

I don't understand how can we use Map.Entry--which is an interface--without redefining Map.Entry's functions.

0xCursor
  • 2,242
  • 4
  • 15
  • 33

8 Answers8

117

Map.Entry is a key and its value combined into one class. This allows you to iterate over Map.entrySet() instead of having to iterate over Map.keySet(), then getting the value for each key. A better way to write what you have is:

for (Map.Entry<String, JButton> entry : listbouton.entrySet())
{
  String key = entry.getKey();
  JButton value = entry.getValue();

  this.add(value);
}

If this wasn't clear let me know and I'll amend my answer.

Paul
  • 19,704
  • 14
  • 78
  • 96
  • Thank you :) But what I'm not understanding is how can we have a variable which its type is The Interface's one ? Normally we implement the interface & redefine all of its functions and we can't create an object with the type of the interface .. Right ? –  Dec 31 '11 at 18:46
  • 4
    If a method returns a collection of objects that implement an `interface`, you don't need to worry about what the underlying object is. In this particular case the object implementing the interface `Map.Entry` is an inner class in whatever `Map` implementation you're using (in this case it's built into `HashMap`). All you need to know is that the object meets the contract specified by the interface, and you can therefore call the methods specified by the interface. – Paul Dec 31 '11 at 18:54
  • What I want to know is: how would you use Map.Entry here without having to retype `String, JButton` over and over? Leaving out the parameters generates frantic warnings from all the compilers I've tried, even though they should be able to deduce the return type of `entrySet()` from examining the type of `listbouton`. – Ti Strga Jan 03 '13 at 15:55
  • if entry object values are modified do they reflect in listbouton object ?? As Java holds shared reference it should be right. –  Sep 29 '16 at 09:00
  • 2
    @LearNer, you are correct. Each entry is a reference to the one held by `listbouton` so changes to an entry will be reflected in the map. Items should not be removed from the map in this loop, however. The proper way to delete objects from a collection while iterating over the collection is to use an `Iterator` and call the `remove` method. – Paul Sep 29 '16 at 12:24
  • @paul thanks a lot, i was trying to delete data entry but it throws error as java.util.ConcurrentModificationException. Is their any way to create a duplicate memory for any class instances?? –  Sep 29 '16 at 13:05
  • 1
    @LearNer, if you want to delete an `Entry` while iterating over the entry set you need to use an `Iterator`: `Iterator> myIter = myMap.entrySet().iterator(); while (myIter.hasNext()) {Map.Entry myEntry = iter.next(); if (delete condition is true) iter.remove();}` – Paul Sep 29 '16 at 14:34
  • @Paul Is Node the object type for variable entry ? – shikhar Jul 26 '17 at 17:20
  • @shikhar I don't understand your question. There's no mention of "Node" in my answer or the original question. – Paul Jul 27 '17 at 13:29
  • I mean inner class Node of HashMap – shikhar Jul 27 '17 at 13:39
  • `Map.Entry` isn't a variable; it's an interface. `Node` is an internal (to `HashMap`) class that implements `Map.Entry`. You don't need to worry about the internal representation, in fact you shouldn't because that may change. You should code to the interface, that is, your code should use `Map.Entry` which is exposed and documented by the API. – Paul Jul 27 '17 at 13:56
5

Note that you can also create your own structures using a Map.Entry as the main type, using its basic implementation AbstractMap.SimpleEntry. For instance, if you wanted to have an ordered list of entries, you could write:

List<Map.Entry<String, Integer>> entries = new ArrayList<>();
entries.add(new AbstractMap.SimpleEntry<String, Integer>(myStringValue, myIntValue));

And so on. From there, you have a list of tuples. Very useful when you want ordered tuples and a basic Map is a no-go.

jytou
  • 510
  • 4
  • 7
2

This code is better rewritten as:

for( Map.Entry me : entrys.entrySet() )
{
    this.add( (Component) me.getValue() );
}

and it is equivalent to:

for( Component comp : entrys.getValues() )
{
    this.add( comp );
}

When you enumerate the entries of a map, the iteration yields a series of objects which implement the Map.Entry interface. Each one of these objects contains a key and a value.

It is supposed to be slightly more efficient to enumerate the entries of a map than to enumerate its values, but this factoid presumes that your Map is a HashMap, and also presumes knowledge of the inner workings (implementation details) of the HashMap class. What can be said with a bit more certainty is that no matter how your map is implemented, (whether it is a HashMap or something else,) if you need both the key and the value of the map, then enumerating the entries is going to be more efficient than enumerating the keys and then for each key invoking the map again in order to look up the corresponding value.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
1

Hash-Map stores the (key,value) pair as the Map.Entry Type.As you know that Hash-Map uses Linked Hash-Map(In case Collision occurs). Therefore each Node in the Bucket of Hash-Map is of Type Map.Entry. So whenever you iterate through the Hash-Map you will get Nodes of Type Map.Entry.

Now in your example when you are iterating through the Hash-Map, you will get Map.Entry Type(Which is Interface), To get the Key and Value from this Map.Entry Node Object, interface provided methods like getValue(), getKey() etc. So as per the code, In your Object you are adding all operators JButtons viz (+,-,/,*,=).

bharatj
  • 2,327
  • 1
  • 25
  • 25
1

A Map is a collection of Key + Value pairs, which is visualized like this:

{[fooKey=fooValue],barKey=barValue],[quxKey=quxValue]}

The Map interface allows a few options for accessing this collection: The Key set [fooKey, barKey,quxKey], the Value set [fooValue, barValue, quxValue] and finally entry Set [fooKey=fooValue],barKey=barValue],[quxKey=quxValue].

Entry set is simply a convenience to iterate over the key value pairs in the map, the Map.Entry is the representation of each key value pair. An equivalent way to do your last loop would be:

for (String buttonKey: listbouton.keySet()) {
    this.add(listbouton.get(buttonKey)) ;
}

or

for (JButton button: listbouton.values()) {
    this.add(button) ;
}
markdsievers
  • 7,151
  • 11
  • 51
  • 83
  • `listbouton` is a `Map` - you can't directly iterate over the keys, you must iterate over `listbouton.keySet`. – Paul Dec 31 '11 at 18:21
1

A Map consists of key/value pairs. For example, in your code, one key is "Add" and the associated value is JButton("+"). A Map.Entry is a single key/value pair contained in the Map. It's two most-used methods are getKey() and getValue(). Your code gets all the pairs into a Set:

Set entrys = listbouton.entrySet() ;

and iterates over them. Now, it only looks at the value part using me.getValue() and adds them to your PanneauCalcul

this.add((Component) me.getValue()) ;   //don't understand

Often this type of loop (over the Map.Entry) makes sense if you need to look at both the key and the value. However, in your case, you aren't using the keys, so a far simpler version would be to just get all the values in your map and add them. e.g.

for (JButton jb:listbouton.values()) {
  this.add(jb);
}

One final comment. The order of iteration in a HashMap is pretty random. So the buttons will be added to your PanneauCalcul in a semi-random order. If you want to preserve the order of the buttons, you should use a LinkedHashMap.

user949300
  • 15,364
  • 7
  • 35
  • 66
0

Map.Entry interface helps us iterating a Map class

Check this simple example:

public class MapDemo {
    public static void main(String[] args) {
     Map<Integer,String> map=new HashMap();
     map.put(1, "Kamran");
        map.put(2, "Ali");
        map.put(3, "From");
        map.put(4, "Dir");
        map.put(5, "Lower");
        for(Map.Entry m:map.entrySet()){
        System.out.println(m.getKey()+"  "+m.getValue());
        }
    }
}
MMSA
  • 810
  • 8
  • 22
Kamran
  • 669
  • 6
  • 9
0

public HashMap<Integer,Obj> ListeObj= new HashMap<>();

public void addObj(String param1, String param2, String param3){
  Obj newObj = new Obj(param1, param2, param3);
  this.ListObj.put(newObj.getId(), newObj);
}

public ArrayList<Integer> searchdObj (int idObj){
  ArrayList<Integer> returnList = new ArrayList<>();
  for (java.util.Map.Entry<Integer, Obj> e : this.ListObj.entrySet()){
    if(e.getValue().getName().equals(idObj)) {
      returnList.add(e.getKey());
    }
  }
return returnList;
}