V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
richieboy
V2EX  ›  Java

for each 居然不能用来赋值..

  •  
  •   richieboy · 2018-06-20 11:58:13 +08:00 · 4706 次点击
    这是一个创建于 2348 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一直以为是等价的..好坑啊,还是老实用 for 循环了

    20 条回复    2018-06-21 10:13:53 +08:00
    Sinar
        1
    Sinar  
       2018-06-20 12:03:47 +08:00 via Android
    赋值用 map 吧
    bumz
        2
    bumz  
       2018-06-20 12:07:44 +08:00
    C++ 就行

    for (auto & a : b) {
    a = 0;
    }
    0x11901
        3
    0x11901  
       2018-06-20 12:11:11 +08:00
    for each 只是遍历,赋值用 map(std::transform)
    LangInteger
        4
    LangInteger  
       2018-06-20 12:13:48 +08:00 via Android
    归根结底,还是因为 java 只有值传递吧~
    bumz
        5
    bumz  
       2018-06-20 12:14:18 +08:00
    @Sinar map 不是赋值,是创建新的吧
    xomix
        6
    xomix  
       2018-06-20 12:38:06 +08:00
    遍历中赋值会导致遍历集合变更,如果要支持便利赋值就要支持便利的时候便利的不再是键值对组合,利用对象复制等功能可以牺牲资源换可读性。

    .net 写法如下,java 我不是很熟练不在这里班门弄斧了。

    Dictionary<string, string> lst = new Dictionary<string, string>() { { "1", "1" }, { "2", "2" } };
    foreach (string key in lst.Keys.ToList())
    {
    lst[key] = lst[key] + "hello";
    }


    这里对 keys 的集合进行了一个 ToList(),实现了一个对象复制,这时候修改原对象就不会造成便利的集合更改了。

    java 可能没有 Linq 支持 ToList()这个方法我就不知道该怎么写了。
    Magentaize
        7
    Magentaize  
       2018-06-20 12:42:39 +08:00 via Android
    foreach 是访问者模式
    Narcissu5
        8
    Narcissu5  
       2018-06-20 13:14:04 +08:00
    foreach 是函数式的方法,函数式的基本特征之一就是不可变。

    也就是如果需要修改的话,返回一个新列表而不是修改之前的
    congeec
        9
    congeec  
       2018-06-20 13:20:15 +08:00 via iPhone
    @Narcissu5 把你这句话里的 foreach 换成 map
    lurenw
        10
    lurenw  
       2018-06-20 13:38:40 +08:00
    java 的 closure 是 capture by value 的。如果要修改,考虑用一个长度为 1 的数组来传外部变量吧。
    ShineSmile
        11
    ShineSmile  
       2018-06-20 13:45:24 +08:00
    没记错 foreach 是与 IEnumable 接口相关?
    0x11901
        12
    0x11901  
       2018-06-20 14:19:21 +08:00   ❤️ 1
    @bumz 你这么写不好,赋值用 auto &&a
    geelaw
        13
    geelaw  
       2018-06-20 14:32:00 +08:00   ❤️ 1
    @bumz #2 那是因为 C++ 的遍历实质上是遍历元素的指针(或者访问器),其他语言是遍历元素的 copy

    @0x11901 #12 为什么?
    geelaw
        14
    geelaw  
       2018-06-20 14:42:27 +08:00
    @0x11901 #12
    @geelaw #13

    I see. 在访问器的情况下 auto & 会失败
    0x11901
        15
    0x11901  
       2018-06-20 15:01:48 +08:00
    @geelaw 对,一般在生产中要改变元素用 auto &&,不变用 const auto &。
    ShineSmile
        16
    ShineSmile  
       2018-06-20 15:05:58 +08:00
    感觉是不是还要详细学一下 yield ?
    ZSeptember
        17
    ZSeptember  
       2018-06-20 16:51:09 +08:00   ❤️ 1
    Java 中的 lambda 捕获的变量只能是 final 或者是实质不可变的。
    以后应该会改成可以捕获可变的吧。
    szq8014
        18
    szq8014  
       2018-06-21 09:48:09 +08:00
    java 里面 foreach 是用 iterator 来实现的
    bumz
        19
    bumz  
       2018-06-21 10:11:13 +08:00
    @0x11901
    @geelaw

    可否简单举例 auto & 失效的情况?
    bumz
        20
    bumz  
       2018-06-21 10:13:53 +08:00
    @bumz I see, 例如 std::vector<bool>
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2834 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:15 · PVG 17:15 · LAX 01:15 · JFK 04:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.