繁体   English   中英

如何使用一对 object ZA2F2ED4F8EBC2CBB4C21A29DC40AB6 将 HashMap 中的值复制到 ArrayList

[英]How to copy values from HashMap into an ArrayList using a Pair object class

所以我想弄清楚如何将我的 Pair<Key, Value> 从它们最初所在的 HashMap 移动到 ArrayList 中。 我所做的一切似乎都不起作用,我不知道如何复制键和值。

class 对:

public class Pair<K,V> {
    private K key;
    private V value;
    public Pair(K key, V value)
    { this.key = key; this.value = value; }
    public K getKey() { return key; }
    public V getValue() { return value; }
}

这是我试图将它们放入的 ArrayList: ArrayList<Pair<String,Integer>> wcList = new ArrayList<>();

对于上面的 ArrayList,我得到了一个 HashMap<String, Integer> 作为参数。 返回必须是 ArrayList<Pair<String, Integer>>

** 使用 entrySet 不适用于我的测试用例 **

这是一个单行。 Stream 取出地图的条目集,并将每个条目转换为Pair 然后将它们收集到一个列表中。

yourMap.entrySet().stream().map(e->new Pair(e.getKey(), e.getValue())).collect(Collectors.toList());

tl;博士

现有的Map.Entry接口可以完成Pair class 的工作,包括getKeygetValue方法。 在您的情况下,请使用Map.Entry < String, Integer >

示例:从学生姓名(键)到他们的年级(值)的Map生成一个键值对List ,首先按他们的年级(最高的在前)排序,然后按他们的姓名字母顺序排序。

var entriesSorted =
        new TreeSet <>(
                Comparator
                        .comparing( Map.Entry < String, Integer > :: getValue ).reversed()  // Reversed for highest grades first.
                        .thenComparing( Map.Entry < String, Integer > :: getKey )  // Names sort alphabetically.
        );
entriesSorted.addAll(
        Map
                .of(
                        "Alice" , 4 ,  // Student, Grade
                        "Bobby" , 2 ,
                        "Carol" , 3 ,
                        "Davis" , 4 ,
                        "Edith" , 1 ,
                        "Frank" , 3
                )
                .entrySet()
);
var list = List.copyOf( entriesSorted );

list.toString() = [爱丽丝=4,戴维斯=4,卡罗尔=3,弗兰克=3,鲍比=2,伊迪丝=1]

或者,如果您坚持使用您的Pair class,请使用Stream#map将密钥和值从每个Map.Entry到新的Pair object。

List < Pair > list =
        Map
                .of(
                        "Alice" , 4 ,  // Student, Grade
                        "Bobby" , 2 ,
                        "Carol" , 3 ,
                        "Davis" , 4 ,
                        "Edith" , 1 ,
                        "Frank" , 3
                )
                .entrySet()  // Returns a `Set` of `Map.Entry` objects.
                .stream()
                .map( entry -> new Pair( entry.getKey() , entry.getValue() ) )
                .toList();

list = [Pair{key=Edith, value=1}, Pair{key=Alice, value=4}, Pair{key=Carol, value=3}, Pair{key=Frank, value=3}, Pair{key =鲍比,价值=2},对{键=戴维斯,价值=4}]

Map.Entry而不是你的Pair

Map已经提供了您想要的。

您暗示您已经有一个Map < String, Integer > ,使用HashMap作为您的实现。

您需要包含在 Map 中的键值对List 为了表示这些键值对,您创建了一个Pair class。 但是不需要您的Pair class Map.Entry接口已经提供了您想要的键值对 object。 引用 Javadoc:

Map.Entry<K,V> ... map 条目(键值对)。

A Map.Entry object 提供getKeygetValue方法,以访问它们的内容。

您可以使用每个Map上的内置方法轻松生成一Set这些Entry对象。

Map< String , Integer > myMap = new HashMap<>() ;
…
Set< String , Integer > pairs = myMap.entrySet() ;

Set在这里是合适的,因为根据定义,您的HashMap没有承诺的订单。 因此,将元素保持在序列中的List没有任何意义。

示例代码

这是一些示例代码,使用映射到 class 成绩的学生姓名。

代替HashMap ,我使用由方便的Map.of方法生成的未指定Map实现。

Map < String, Integer > studentGrades =
        Map.of(
                "Alice" , 4 ,
                "Bob" , 2 ,
                "Carol" , 3 ,
                "Davis" , 4 ,
                "Edith" , 1 ,
                "Frank" , 3
        );
Set < Map.Entry < String, Integer > > entries = studentGrades.entrySet();
entries.forEach( System.out :: println );  // Call `toString` on each `Entry` object.

运行时:

Davis=4
Edith=1
Alice=4
Bob=2
Carol=3
Frank=3

你不需要计算出Set < Map.Entry < String, Integer > > entries的确切类型; 只需使用var让编译器弄清楚。

var entries = studentGrades.entrySet();

有序集

var entries = studentGrades.entrySet();

如果您想按特定顺序保留这些条目,请使用NavigableSet (或SortedSet ),例如TreeSet 您需要提供订购它们的规则。

假设我们希望它们按学生的成绩排序,首先是最高成绩。

NavigableSet < Map.Entry < String, Integer > > entriesByGrade =
        new TreeSet <>(
                Comparator
                        .comparing( Map.Entry < String, Integer > :: getValue ).reversed()
                        .thenComparing( Map.Entry < String, Integer > :: getKey )
        );
entriesByGrade.addAll( entries );

entryByGrade.toString() = [爱丽丝=4,戴维斯=4,卡罗尔=3,弗兰克=3,鲍勃=2,伊迪丝=1]

如果你真的需要一个List ,你可以从NavigableSet中创建一个。

List < Map.Entry < String, Integer > > listOfStudentsByGrade = List.copyOf( entriesByGrade );

或者更简单地说,使用var

var listOfStudentsByGrade = List.copyOf( entriesByGrade );

无论哪种方式,运行时:

listOfStudentsByGrade.toString() = [爱丽丝=4,戴维斯=4,卡罗尔=3,弗兰克=3,鲍勃=2,伊迪丝=1]

使用您的Pair class

正如本答案和评论中所讨论的,您的Pair class 完全是多余的, Map.Entry已经完成了它的工作。

但是,如果您坚持,您可以轻松地从每个条目中提取键和值,然后将相同的键和值放入您的Pair class 的 object 中。 愚蠢,但很容易。

List < Pair > list =
        Map
                .of(
                        "Alice" , 4 ,  // Student, Grade
                        "Bobby" , 2 ,
                        "Carol" , 3 ,
                        "Davis" , 4 ,
                        "Edith" , 1 ,
                        "Frank" , 3
                )
                .entrySet()
                .stream()
                .map( entry -> new Pair( entry.getKey() , entry.getValue() ) )
                .toList();

这是填充 Map 的代码,然后打印出 map 内容:

Map<String, Integer> map = new HashMap<>();
map.put("aardvark", 1);
map.put("bear", 2);
map.put("cat", 3);
System.out.println("map: " + map);

map: {cat=3, aardvark=1, bear=2}

使用 map,这里有一些代码:

  • 从 map 获取每个密钥
  • 对于每个键,获取关联的值
  • 对于每个键值对,它会创建一个新的 Pair object(使用您发布的 Pair 代码)
  • 然后将每对添加到列表中
  • 最后,它打印出列表的内容
  • 另外,我在 Pair class 中添加了一个toString()方法(发布在下面),以便列表打印提供更多信息
List<Pair<String, Integer>> list = new ArrayList<>();
for (String key : map.keySet()) {
    Integer value = map.get(key);
    Pair<String, Integer> pair = new Pair<>(key, value);
    list.add(pair);
}
System.out.println("list: " + list);

list: [Pair{key=cat, value=3}, Pair{key=aardvark, value=1}, Pair{key=bear, value=2}]

这是对 Pair 的补充,以便可以很好地打印列表内容:

@Override
public String toString() {
    return "Pair{" +
            "key=" + key +
            ", value=" + value +
            '}';
}

您也可以使用流解决它:

List<Pair<String, Integer>> list = map
        .keySet()
        .stream()
        .map(key -> new Pair<>(key, map.get(key)))
        .toList();

下面的代码将键和值从 HashMap 中分离出来,并创建 2 个 ArrayList 来保存它们。

请参考提取方法。

对于上面的 ArrayList,我得到了一个 HashMap<String, Integer> 作为参数。 返回必须是 ArrayList<Pair<String, Integer>>

public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("one", 1);
    map.put("two", 2);
    map.put("three", 3);
    extract(map);
}

public static ArrayList<Pair<String, Integer>> extract(HashMap map)
{
    ArrayList<Pair<String, Integer>> list = new ArrayList<Pair<String,Integer>>();
    ArrayList<String> mapKeys = new ArrayList<String>(map.keySet());
    ArrayList<Integer> mapValues = new ArrayList<Integer>(map.values());
    Pair p;
    for(int i=0; i<map.size(); i++) {
        p = new Pair(mapKeys.get(i), mapValues.get(i));
        list.add(p);
    }
    
    list.stream().forEach(e ->System.out.println(e.toString()));
    return list;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM