I have a Set A:
[{name: a,value: 10},
{name: b,value: 11}]
and Set B:
[{name: a,value: 100},
{name: b,value: 110}]
Then, I want get Map C:
{{name: a,value: 10}:{name: a,value: 100},
{name: b,value: 11}:{name: b,value: 110}}
The key and the the value of each Entry in Map C are equal, which means that the key and the value has the same "name", through different "value"s. I found guava's Sets is useful, but lack of such functions.
I know this is one way to do that:
public static <T> Map<T, T> zip(Set<T> s1, Set<T> s2) {
Map<T, T> map = new HashMap<>();
for (T e1 : s1) {
for (T e2 : s2) {
if (e1.equals(e2)) {
map.put(e1, e2);
break;
}
}
}
return map;
}
Is there any convenient way to zip two sets in Java?
You could try this, for this to work override equals and hashcode with field name
public static <T> Map<T, T> zip(Set<T> s1, Set<T> s2) {
return s1.stream()
.filter(s2::contains)
.collect(Collectors.toMap(k -> k, v -> s2.stream().filter(s -> s.equals(v)).findFirst().get()));
}
The implementation you specified has complexity O(n^2). You can write it as O(n) as follows:
public static <T> Map<T, T> zip(Set<T> s1, Set<T> s2) {
Map<T, T> map = new HashMap<>();
for (T e1 : s1) {
T e2 = s2.get(e1) {
if (e1.equals(e2)) {
map.put(e1, e2);
break;
}
}
return map;
}
This is O(n) because get()
uses hashing to find the element. For this to work correctly, you need to implement hashCode()
and equals()
for the actual type passed as T
to behave properly:
class Actual {
private String name;
private String value;
...
public int hashCode() {
return name.hashCode()
}
public boolean equals(Object o) {
if (!(o instanceof Actual)) {
return false;
}
Actual other = (Actual)o;
return name.equals(other.name);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.