如何转换集合<pair <k,集合<v =“”>&gt;到列表<myobject <k,v>&gt;使用Java流API?

时间:2018-01-24 13:26:20

标签: java lambda

我的传统代码如下所示:

List<MyObject> transform(Collection<java.util.Map.Entry<String, List<String>>> input) {
    List<MyObject> output = new LinkedList<>();
    for (Entry<String, List<String>> pair : input) {
        for (String value : pair.getValue()) {
            output.add(new MyObject(pair.getKey(), value));
        }
    }
    return output;
}

我可以用lambda表达式做同样的事情吗?我试过了,但我没理解。外部集合未排序,但List<String>已排序。结果对象可以在结果列表中返回而没有任何顺序,除了从相同的键String创建的对象应该彼此跟随以保持值的顺序。这有可能吗?

2 个答案:

答案 0 :(得分:4)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Background Test</title>
    <style>
        * {  margin: 0;  padding: 0;  overflow: hidden;  }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>

    <script>

    // Request animation frame -> Optimizes animation speed
    const requestAnimationFrame = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame;

    const c = document.getElementById('canvas');
    const ctx = c.getContext('2d');

    // Fullscreen
    c.width = window.innerWidth;
    c.height = window.innerHeight;

    ctx.fillStyle = 'red';

    let fps = 60;

    // FOR MOBILE DEVICES
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
        fps = 29;

    // Options
    const background = '#333';
    const circleMinSpeed = 3;
    const circleMaxSpeed = 6;
    const circleMinSize  = 3;
    const circleMaxSize  = 10;
    const circles = [];
    let circlesCounter = 0;
    const circlesTimeAlive = 20 * fps; // seconds
    let i = 0;

    const interval = 1000 / fps;

    let now, delta;
    let then = Date.now();

    // Coordinate variables
    let mouseX, mouseY, clickX, clickY;

    // Tracks mouse movement
    c.onmousemove = function(event)
    {
        mouseX = event.clientX;
        mouseY = event.clientY;
    };

    // Tracks mouse click
    c.onmousedown = function(event)
    {
        clickX = event.clientX;
        clickY = event.clientY;
        circle(clickX, clickY);
    };

    function draw()
    {
        // Loop
        requestAnimationFrame(draw);

        // Set NOW and DELTA
        now = Date.now();
        delta = now - then;

        // New frame
        if (delta > interval) {
            // Update THEN
            then = now - (delta % interval);
            // Our animation
            // Clear canvas then draw
            ctx.clearRect(0, 0, c.width, c.height);
            drawBackground();
            drawCos();
            drawCircles();
            drawTest();
        }
    }

    // Circle constructor
    function circle(x, y)
    {
        // Pick random color
        let r = Math.floor(Math.random() * 255);
        let g = Math.floor(Math.random() * 255);
        let b = Math.floor(Math.random() * 255);

        self.color = 'rgb(' + r + ', ' + g + ', ' + b + ')';

        self.xCo = x;
        self.yCo = y;

        // Pick random size within ranges
        self.size = circleMinSize + Math.floor(Math.random() *
            (circleMaxSize - circleMinSize));

        // Pick random direction & speed (spdX spdY)
        self.speed = circleMinSpeed + Math.floor(Math.random() *
            (circleMaxSpeed - circleMinSpeed));
        self.spdX = self.speed * (Math.random() * 2) - 1; // picks -1 to 1
        self.spdY = self.speed * (Math.random() * 2) - 1;

        self.draw = function()
        {
            ctx.beginPath();
            ctx.arc(self.xCo, self.yCo, self.size, 0, 2*Math.PI);
            ctx.fillStyle = self.color;
            ctx.fill();
        };

        circles[circlesCounter++] = self;
    }

    // Draw the background
    function drawBackground()
    {
        ctx.fillStyle = background;
        ctx.fillRect(0, 0, c.width, c.height);
    }

    function drawCircles()
    {
        for (let i = 0; i < circles.length; i++)
            circles[i].draw();
    }

    function drawTest()
    {
        ctx.fillStyle = 'red';
        ctx.fillRect(i++, i, 5, 5);
    }

    function drawCos()
    {
        ctx.fillStyle = 'white';
        ctx.fillText("X: " + mouseX + " Y:" + mouseY, 10, 10, 200);
    }

    // Main loop
    setInterval(function()
    {
        // Loop through circles and move them
        for (let i = 0; i < circles.length; i++)
        {
            if (circle[i])
            {
                // Check left and right bounce
                if (circle[i].xCo <= 0 || circle[i].xCo >= c.width)
                    circle[i].spdX = -circle[i].spdX;
                circle[i].xCo += circle[i].spdX;

                // Check left and right bounce
                if (circle[i].yCo <= 0 || circle[i].yCo >= c.height)
                    circle[i].spdY = -circle[i].spdY;

                circle[i].yCo += circle[i].spdY;
            }
        }

        // Draw Everything
        draw();
    }, interval);

    </script>
</body>
</html>

答案 1 :(得分:2)

您可以像this answer一样使用流和Stream.flatMap,但是我认为如果你坚持使用循环,或者你的问题中的传统循环或现代循环,代码会更清晰:

List<MyObject> output = new LinkedList<>();
input.forEach(pair -> pair.getValue()
     .forEach(value -> output.add(new MyObject(pair.getKey(), value))));

顺便说一句,我使用的是ArrayList而不是LinkedList