yangxu998 / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Create / populate Map from Iterable of any type #679

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This request is similar to the following two issues, but more generic. These 
two issues request a new version of Maps.uniqueIndex that takes in keys instead 
of values. A more generic version would be a map method that would take an 
iterator of any type and use a function to determine both the key and value. 

Similar Issue:
http://code.google.com/p/guava-libraries/issues/detail?id=56
http://code.google.com/p/guava-libraries/issues/detail?id=460

Suggested generalized version signatures (implementation attached):

// First version with a separate function for key and value which would allow 
for the use of the identity function.
public static <I, K, V> Map<K, V> map(Iterable<I> input, Function<I, K> 
keyFunction, Function<I, V> valueFunction);

public static <I, K, V> void addToMap(Iterable<I> input, Map<K, V> map, 
Function<I, K> keyFunction, Function<I, V> valueFunction);

// Second version which uses a single function to retrieve both key and value
public static <I, K, V> Map<K, V> map(Iterable<I> input, Function<I, 
Map.Entry<K, V>> transform);

public static <I, K, V> void addToMap(Iterable<I> input, Map<K, V> map, 
Function<I, Map.Entry<K, V>> transform);

There are two versions of each of the method to allow for the passing of a 
specific Map type rather than being locking into getting a HashMap.

Original issue reported on code.google.com by dancerj...@gmail.com on 8 Aug 2011 at 1:20

Attachments:

GoogleCodeExporter commented 9 years ago
Not convinced of the widespread need for these yet, but we'll see.

Original comment by kevin...@gmail.com on 1 Sep 2011 at 5:38

GoogleCodeExporter commented 9 years ago
I've felt the need for this kind of method many times when loading maps using 
results from a database query.

Original comment by andre...@gmail.com on 1 Sep 2011 at 6:17

GoogleCodeExporter commented 9 years ago
My point is that rather than moving forward with the other issues listed above, 
this would be a more generic solution and should be used instead. The identity 
function in combination with this version would produce the effect requested in 
the other issues.

Original comment by dancerj...@gmail.com on 1 Sep 2011 at 6:44

GoogleCodeExporter commented 9 years ago
I would rather love to see such a function in ImmutableMap.Builder<K,V>.

public <E> ImmutableMap.Builder<K,V> putAll(Iterable<? extends E> iterable, 
Function<? super E,K> keyFunction, Function<? super E,V> valueFunction);

I think this makes you even more flexible in map creation. In that way it would 
also replace uniqueIndex and add the requested uniqueValue if one passes the 
identity function as either the keyFunction or valueFunction.

Original comment by christop...@gmail.com on 8 Oct 2011 at 8:04

GoogleCodeExporter commented 9 years ago

Original comment by fry@google.com on 10 Dec 2011 at 4:14

GoogleCodeExporter commented 9 years ago

Original comment by fry@google.com on 16 Feb 2012 at 7:17

GoogleCodeExporter commented 9 years ago
What parts of this issue aren't covered by the Idea Graveyard nix on "create a 
map from an Iterable<Pair>, Iterable<Map.Entry>, Object[] (alternating keys and 
values), or from List<K> + List<V>"?

Original comment by wasserman.louis on 23 Feb 2012 at 7:28

GoogleCodeExporter commented 9 years ago
Of course there is not an explanation about why this idea was rejects, but in 
the case of the Graveyard idea, both elements (key and value) are already being 
passed in. I am referring to a case were the key and value are calculated based 
on some input.

There has been a deemed need to have the following:
1. Map<K, V> uniqueIndex(Iterable<V>, Function<V,K>) (already exists)
2. Map<K, V> uniqueIndex(Iterable<K>, Function<K,V>) (issue 56 & 460)

However, what if the input is neither the key nor the value? Hence the need for:
3. Map<K,V> uniqueIndex(Iterable<T>, Function<T,K>, Function<T,V>)

It seems that the above single function (3) covers both case 1 & 2 above (with 
use of the Identity function) and allows for an additional case where the input 
is neither the key nor value. 

The case could be made that you could convert the input to either the key or 
value and use one of the methods 1 or 2 above, but what if the key cannot be 
calculated from the value of vise versa.

It seems odd to me to have two methods where one would work especially 
considering the focus of reducing API bloat.

Original comment by dancerj...@gmail.com on 23 Feb 2012 at 8:41

GoogleCodeExporter commented 9 years ago
Do you have an actual use case in mind?  We're having some trouble coming up 
with anything realistic.

Original comment by wasserman.louis on 23 Feb 2012 at 9:46

GoogleCodeExporter commented 9 years ago
For what it's worth, I just arrived at this issue while trying to find a way to 
generate a lookup table for "named" objects.  I thought it would be a common 
case: I have an iterable of objects that have names, and wanted to construct a 
map from each name to the associated instance.

I wouldn't have said anything normally, but it struck me that if I didn't, you 
wouldn't know that just a day after one person mentions it, another is also 
looking...

Original comment by acooke....@gmail.com on 24 Feb 2012 at 3:59

GoogleCodeExporter commented 9 years ago
acooke,

Is the method you need the existing Maps.uniqueIndex?

Original comment by cpov...@google.com on 24 Feb 2012 at 4:04

GoogleCodeExporter commented 9 years ago
It sure sounds like it.  Maps.uniqueIndex(namedObjects, nameFunction) is 
exactly the right solution for that use case.

Original comment by wasserman.louis on 24 Feb 2012 at 4:07

GoogleCodeExporter commented 9 years ago
What about a case where there is a list of Files (say the files in a directory) 
and there is a need to create a Map<String, Object> where the key is the file 
name and the Object is some data that is parsed from the file.

Original comment by dancerj...@gmail.com on 7 Mar 2012 at 4:10

GoogleCodeExporter commented 9 years ago
What about that case? I'm not sure what you're driving at.  That's either 
appropriate for issue 56, or you should be doing it explicitly -- especially in 
case of IOExceptions.

Original comment by wasserman.louis on 7 Mar 2012 at 4:33

GoogleCodeExporter commented 9 years ago

Original comment by kevinb@google.com on 30 May 2012 at 7:43

GoogleCodeExporter commented 9 years ago

Original comment by kevinb@google.com on 22 Jun 2012 at 6:16

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Our use case is similar to this:

class Option { String id; String valueId; }

Locale locale = ...;
Iterable<Option> it = ...;
Map<String, String> m = Maps.newLinkedHashMap();
for (Option o : it) {
    m.put(o.id, translate(locale, o.valueId));
}
ImmutableMap<String, String> result = ImmutableMap.copyOf(m);

Which would be used to generate:

<input type="radio" name="id1" value="translatedValue1">
<input type="radio" name="id2" value="translatedValue2">
...

Original comment by sebastia...@gmail.com on 31 Oct 2012 at 1:01

GoogleCodeExporter commented 9 years ago
I need such method to convert org.w3c.dom.NamedNodeMap to Map<String, String>

Original comment by advoret...@gmail.com on 16 Dec 2012 at 4:49

GoogleCodeExporter commented 9 years ago
A NamedNodeMap doesn't fit in here at all, as it doesn't implement any of the 
standard java.util interfaces, such as Collection, Iterable or Map. 

Original comment by SeanPFl...@googlemail.com on 17 Dec 2012 at 8:56

GoogleCodeExporter commented 9 years ago
Yeah, I am ready to wrap it to Iterable, but after that I would like to use 
guava for producing comfortable (for asserts in test) Map<String, String>

Original comment by advoret...@gmail.com on 17 Dec 2012 at 9:15

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
For what it's worth, just came across a need to generate a map from a list of 
objects.  It would be nice if Map.values were allowed to be transformations of 
the objects in the list, while the keys were allowed to be computed via the 
supplied function, all in one method call.  If anyone is interested in the use 
case, it is the zadd operation on Redis that accepts multiple members:

zadd(final byte key, final Map<Double, byte[]> scoreMembers)

The Double parameter is a score or priority of any given member that should be 
computed from the object on the fly.

Original comment by yuri.pan...@gmail.com on 5 Aug 2013 at 4:50

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:18

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:09