如何分组超过字段和结果是List

时间:2018-06-19 06:40:47

标签: lambda java-8

有一个java类:

 public class Test {
    private Integer parentId;
    private Integer systemId;
    private Integer id;
    private Integer weight;

    //With their setter and getter

    }

并且有一个Test类(List<Test>)的集合,其数据如下:

parentId    systemId      id       weight
------------------------------------------
10          100           1          200
10          100           2          300
10          300           3          400
20          400           4          200
20          400           5          600
20          500           6          6 
20          500           7          4

我想通过parentId和systemId进行分组,分组的结果是List不是Map。

分组后,列表内容将为:

parentId    systemId      weight
---------------------------------
10             100           500  
10             300           400
20             400           800
20             500           10

分组结果List不是Map

非常重要

5 个答案:

答案 0 :(得分:0)

就像这样。您可以将<?php header("Access-Control-Allow-Origin: *"); if(isset($_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Max-Age: 86400'); // cache for 1 day } //Access-Control headers are received during OPTIONS requests if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit(0); } $con = mysqli_connect("localhost","root","upload","ampache"); // Check connection if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } $postdata = file_get_contents("php://input"); if(isset($postdata)) { $request = json_decode($postdata); $name = $request->testname; $id = $request->testid; $file = $request->testfile; $filename = basename("c:\fakepath\ $file"); echo $filename; $artist_name = $request->testartist; $catalog = 1; $enabled = 1; $channels = 2; $update_time = 0; $user_upload = 1; $bitrate = 192000; $rate = 44100; $mode = "cbr"; $filepath = 'C:\\\xampp\\\htdocs\\\ampache-3.8.6_all\\\songs\\\admin\\\ '; $audiopath = $filepath.$artist_name."/".$name."\\\ ".$filename; $path = mkdir("C:/xampp/htdocs/ampache-3.8.6_all/songs/admin/" . $artist_name . "/" . $name. "/", 0700); if($name != "" && $id != "") { $con = mysqli_connect("localhost","root","upload","ampache"); // Check connection if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } else { //echo "Name: " .$name; //echo "id: " .$id; //$sql = "INSERT INTO album(name, album_artist) VALUES // ('$name', '$id')"; $sql = "INSERT INTO album(name, album_artist) VALUES ('$name', '$id')"; $stmt = mysqli_query($con, $sql) or die ("MySQL Error:".mysqli_error($con)); echo "successfully inserted !"; } $lastid = mysqli_insert_id($con); $sql1 = "INSERT INTO song(catalog, enabled, channels, update_time, user_upload, mode, bitrate, rate, artist, album, title, file) VALUES ('$catalog', '$enabled', '$channels', '$update_time', '$user_upload', '$mode', '$bitrate', '$rate', '$id', '$lastid', '$filename', '$audiopath')"; $stmt1 = mysqli_query($con, $sql1) or die ("MySQL Error:".mysqli_error($con)); } else { echo "Empty name and description parameter!"; } } else { echo "Not called properly with name and description parameter!"; } ?> 与合并功能结合使用。

toMap

然后将其转换为HashMap<Pair<Integer, Integer>, Integer> map = list.stream() .collect(Collectors .toMap(item -> new Pair<>(item.parentId, item.systemId), item -> item.weight, Integer::sum, LinkedHashMap::new)); 列表。

Test(Integer parentId, Integer systemId, Integer weight)

答案 1 :(得分:0)

这应该这样做,

Map<Integer, Map<Integer, List<Test>>> groupMap = test.stream()
        .collect(Collectors.groupingBy(Test::getParentId, Collectors.groupingBy(Test::getSystemId)));
List<Test> orderedObjects = groupMap.entrySet().stream()
        .flatMap(e -> e.getValue().entrySet().stream()
                .map(mp -> mp.getValue().stream().reduce((t1, t2) -> new Test(t1.getParentId(),
                        t1.getSystemId(), t1.getId(), t1.getWeight() + t2.getWeight())).orElse(null)))
        .collect(Collectors.toList());

答案 2 :(得分:0)

没有明确需要首先以Map的形式获得结果,然后转换为List

这是直接返回List的解决方案。关键的想法是将具有相同TestparentId的所有systemId对象减少到包含Test字段总和的结果weight对象。 / p>

但是,您必须覆盖equals()类的hashCode()Test方法。

以下是解决方案:

inputList = new ArrayList<>(
    Arrays.asList(
            new Test(10, 100, 1, 200),
            new Test(10, 100, 2, 300),
            new Test(10, 300, 3, 400),
            new Test(20, 400, 4, 200),
            new Test(20, 400, 5, 600),
            new Test(20, 500, 6, 6),
            new Test(20, 500, 7, 4)
    )
);

BinaryOperator<Test> accumulator = (d1, d2) -> 
    new Test(d1.getParentId(), d1.getSystemId(), d1.getWeight() + d2.getWeight());

List<Test> resultList = inputList.stream()
                                .map(test1 -> inputList.stream()
                                        .filter(test2 -> !(test1.getId().equals(test2.getId())) && test1.getParentId().equals(test2.getParentId()) && test1.getSystemId().equals(test2.getSystemId()))
                                        .reduce(new Test(test1.getParentId(), test1.getSystemId(), test1.getWeight()), accumulator)
                                )
                                .distinct()
                                .collect(Collectors.toList());

equals()类的被覆盖的hashCode()Test方法(仅供参考):

@Override
public boolean equals(Object obj){
    if(obj == null)
        return false;

    Test d2 = (Test)obj;
    if (parentId.equals(d2.getParentId()) && systemId.equals(d2.getSystemId()) && weight.equals(d2.getWeight())) {
        if (id != null) {
            if (id.equals(d2.getId())) {
                return true;
            } else{
                return false;
            }
        }
        return true;
    }
    return false;
}

@Override
public int hashCode() {
    int hash = 7;
    hash = 71 * hash + Objects.hashCode(this.parentId);
    hash = 71 * hash + Objects.hashCode(this.systemId);
    hash = 71 * hash + Objects.hashCode(this.weight);
    return hash;
}

我没有在id方法中使用equals()字段,因为在所需的输出中省略了该字段。

答案 3 :(得分:0)

混合溶液怎么样?您可以在 @Ravindra Ranwala 答案中找到Stream解决方案。它有效,但我认为这对于实现和支持来说有点复杂。我提供了另一种解决方案,对我来说更清楚。

这是将List<Test>合并到Test的功能。我认为将其与组逻辑分开是更清楚的。这次它只是对给定列表中的所有weight求和。您可以在此处添加更多字段。

Function<List<Test>, Test> merge = notEmptyGroup -> {
    Test test = notEmptyGroup.iterator().next();
    int weight = notEmptyGroup.stream().map(Test::getWeight).mapToInt(w -> w).sum();
    return new Test(test.getParentId(), test.getSystemId(), weight);
};

这是分组方法。这只是组逻辑和merge函数,它接受要合并的一个组中的所有Test

public static List<Test> groupByParentIdAndSystemId(List<Test> tests, Function<List<Test>, Test> merge) {
    List<Test> results = new LinkedList<>();

    Map<Integer, Map<Integer, List<Test>>> map = tests.stream().collect(Collectors.groupingBy(Test::getParentId,
            Collectors.groupingBy(Test::getSystemId)));

    map.values().forEach(parentTests ->
            parentTests.values().forEach(systemTests ->
                    results.add(merge.apply(systemTests))));   
    results.sort(Comparator.comparingInt(Test::getParentId).thenComparingInt(Test::getSystemId));

    return results;
}

这是客户端代码:

List<Test> res = groupByParentIdAndSystemId(tests, merge);

答案 4 :(得分:0)

com.google.android.material.bottomappbar.BottomAppBar

android.support.design.bottomappbar.BottomAppBar

结果

Map<Integer, Map<Integer, Integer>> groupped = input.stream()
        .collect(Collectors.groupingBy(Test::getParentId,Collectors.groupingBy(Test::getSystemId,Collectors.summingInt(Test::getWeight))));

Stream<List<Test>> stream = groupped.entrySet().stream().map(grouppedEntry -> {
    Integer parentId = grouppedEntry.getKey();
    return grouppedEntry
            .getValue().entrySet().stream().map(systemIdAndSummedWeight -> new Test(parentId,
                    systemIdAndSummedWeight.getKey(), systemIdAndSummedWeight.getValue()))
            .collect(Collectors.toList());
});

List<Test> result = stream.flatMap(List::stream).sorted(
        Comparator.comparing(Test::getParentId).thenComparing(Comparator.comparing(Test::getSystemId)))
        .collect(Collectors.toList());