简体   繁体   English

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

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

So I am trying to figure out how to move my Pair<Key, Value> from the HashMap that they are originally in, into an ArrayList.所以我想弄清楚如何将我的 Pair<Key, Value> 从它们最初所在的 HashMap 移动到 ArrayList 中。 Nothing I am doing seems to be working and I am at a loss for how to copy the Keys & Values over.我所做的一切似乎都不起作用,我不知道如何复制键和值。

The Pair class: 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; }
}

And here is the ArrayList that I am attempting to put them into: ArrayList<Pair<String,Integer>> wcList = new ArrayList<>();这是我试图将它们放入的 ArrayList: ArrayList<Pair<String,Integer>> wcList = new ArrayList<>();

For the above ArrayList I am given a HashMap<String, Integer> as a parameter.对于上面的 ArrayList,我得到了一个 HashMap<String, Integer> 作为参数。 The return must be an ArrayList<Pair<String, Integer>>返回必须是 ArrayList<Pair<String, Integer>>

** Using an entrySet does not work for my test cases ** ** 使用 entrySet 不适用于我的测试用例 **

This is a one-liner.这是一个单行。 Stream out the map's entry set, and convert each entry to a Pair . Stream 取出地图的条目集,并将每个条目转换为Pair Then collect them into a list.然后将它们收集到一个列表中。

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

tl;dr tl;博士

The existing Map.Entry interface does the job of your Pair class, including getKey & getValue methods.现有的Map.Entry接口可以完成Pair class 的工作,包括getKeygetValue方法。 In your case, use Map.Entry < String, Integer > .在您的情况下,请使用Map.Entry < String, Integer >

Example: From a Map of student name (key) to their grade (value), produce a List of the key-value pairings, sorted first by their grade (highest first), then by their name alphabetically.示例:从学生姓名(键)到他们的年级(值)的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() = [Alice=4, Davis=4, Carol=3, Frank=3, Bobby=2, Edith=1] list.toString() = [爱丽丝=4,戴维斯=4,卡罗尔=3,弗兰克=3,鲍比=2,伊迪丝=1]

Or, if you insist upon your Pair class, use Stream#map to transfer the key & value from each Map.Entry to a new Pair object.或者,如果您坚持使用您的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=Bobby, value=2}, Pair{key=Davis, value=4}] 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 instead of your Pair Map.Entry而不是你的Pair

A Map already provides what you want. Map已经提供了您想要的。

You imply that you already have a Map < String, Integer > , using HashMap as your implementation.您暗示您已经有一个Map < String, Integer > ,使用HashMap作为您的实现。

You want a List of the key-value pairs contained in that Map.您需要包含在 Map 中的键值对List To represent those key-value pairs, you created a Pair class.为了表示这些键值对,您创建了一个Pair class。 But there is no need for your Pair class .但是不需要您的Pair class The Map.Entry interface already provides the key-value pairing object you desire. Map.Entry接口已经提供了您想要的键值对 object。 To quote the Javadoc:引用 Javadoc:

Map.Entry<K,V> … A map entry (key-value pair). Map.Entry<K,V> ... map 条目(键值对)。

A Map.Entry object offers getKey and getValue methods, to access their contents. A Map.Entry object 提供getKeygetValue方法,以访问它们的内容。

You can easily produce a Set of those Entry objects, with a built-in method on every Map .您可以使用每个Map上的内置方法轻松生成一Set这些Entry对象。

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

A Set is appropriate here, because your HashMap by definition has no promised order. Set在这里是合适的,因为根据定义,您的HashMap没有承诺的订单。 So a List , which keeps elements in a sequence, makes no sense.因此,将元素保持在序列中的List没有任何意义。

Example code示例代码

Here is some example code, using student name mapped to their class grade.这是一些示例代码,使用映射到 class 成绩的学生姓名。

Instead of a HashMap , I use an unspecified Map implementation produced by the convenient Map.of method.代替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.

When run:运行时:

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

You needn't work out that exact type of Set < Map.Entry < String, Integer > > entries ;你不需要计算出Set < Map.Entry < String, Integer > > entries的确切类型; just use var to let the compiler figure it out.只需使用var让编译器弄清楚。

var entries = studentGrades.entrySet();

Ordered set有序集

var entries = studentGrades.entrySet();

If you want to keep those entries in a specific order, use a NavigableSet (or SortedSet ) such as TreeSet .如果您想按特定顺序保留这些条目,请使用NavigableSet (或SortedSet ),例如TreeSet You will need to provide the rule by which to order them.您需要提供订购它们的规则。

Let's say we want them sorted by the student's grades, highest grades first.假设我们希望它们按学生的成绩排序,首先是最高成绩。

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 );

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

If you really need a List , you can make one from the NavigableSet .如果你真的需要一个List ,你可以从NavigableSet中创建一个。

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

Or more simply, use var .或者更简单地说,使用var

var listOfStudentsByGrade = List.copyOf( entriesByGrade );

Either way, when run:无论哪种方式,运行时:

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

Using your Pair class使用您的Pair class

As discussed in this Answer, and in the Comments, your Pair class is utterly superfluous, with Map.Entry already doing its job.正如本答案和评论中所讨论的,您的Pair class 完全是多余的, Map.Entry已经完成了它的工作。

But if you insist, you could easily pull the key & value out of each entry, then put that same key and value into an object of your Pair class.但是,如果您坚持,您可以轻松地从每个条目中提取键和值,然后将相同的键和值放入您的Pair class 的 object 中。 Silly, but easy.愚蠢,但很容易。

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();

Here's a bit of code that populates a Map, and then prints out the map contents:这是填充 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}

Using that map, here's a bit of code that:使用 map,这里有一些代码:

  • gets each key from the map从 map 获取每个密钥
  • for each key, gets the associated value对于每个键,获取关联的值
  • for each key-value pair, it creates a new Pair object (using the Pair code you posted)对于每个键值对,它会创建一个新的 Pair object(使用您发布的 Pair 代码)
  • each Pair is then added to a List然后将每对添加到列表中
  • at the end, it prints out the contents of the list最后,它打印出列表的内容
  • also, I added a toString() method to the Pair class (posted below) so that the list printing is more informative另外,我在 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}]

Here's the addition to Pair so that the list contents can be printed nicely:这是对 Pair 的补充,以便可以很好地打印列表内容:

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

You could also solve it with streams:您也可以使用流解决它:

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

The below code seperates the keys and values from HashMap and creates 2 ArrayLists to hold them.下面的代码将键和值从 HashMap 中分离出来,并创建 2 个 ArrayList 来保存它们。

Please refer the extract method.请参考提取方法。

For the above ArrayList I am given a HashMap<String, Integer> as a parameter.对于上面的 ArrayList,我得到了一个 HashMap<String, Integer> 作为参数。 The return must be an ArrayList<Pair<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