当前位置: 首页 > 知识库问答 >
问题:

羊羔和猪不见了

南门峰
2023-03-14

我在这里发布了一个答案,其中演示使用< code>ConcurrentMap的< code>putIfAbsent方法的代码如下:

ConcurrentMap<String, AtomicLong> map = new ConcurrentHashMap<String, AtomicLong> ();

public long addTo(String key, long value) {
  // The final value it became.
  long result = value;
  // Make a new one to put in the map.
  AtomicLong newValue = new AtomicLong(value);
  // Insert my new one or get me the old one.
  AtomicLong oldValue = map.putIfAbsent(key, newValue);
  // Was it already there? Note the deliberate use of '!='.
  if ( oldValue != newValue ) {
    // Update it.
    result = oldValue.addAndGet(value);
  }
  return result;
}

这种方法的主要缺点是您必须创建一个新对象来放入地图中,无论它是否会被使用。如果对象很重,这可能会产生重大影响。

我想到这将是一个使用Lambdas的机会。我还没有下载Java 8 n,或者在它成为官方(公司政策)之前我可以下载,所以我无法测试它,但这样的东西是否有效?

public long addTo(String key, long value) {
  return map.putIfAbsent( key, () -> new AtomicLong(0) ).addAndGet(value);
}

我希望使用lambda来延迟对新AtomicLong(0)的求值,直到它实际确定应该创建它,因为它不存在于映射中。

如您所见,这更加简洁和实用。

基本上我想我的问题是:

  1. 这行吗
  2. 还是我完全误解了兰达斯
  3. 也许有一天会有这样的效果

共有3个答案

柳羽
2023-03-14

不幸的是,这并没有那么容易。您概述的方法有两个主要问题:1.地图的类型需要从Map更改

然而,有一个按需运行函数来填充缺失值的地图的想法是一个很好的想法,事实上谷歌的番石榴库有一个地图可以做到这一点;参见他们的MapMaker。事实上,代码将受益于Java8个lambda表达式:而不是

   ConcurrentMap<Key, Graph> graphs = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .makeComputingMap(
           new Function<Key, Graph>() {
             public Graph apply(Key key) {
               return createExpensiveGraph(key);
             }
           });

你就可以写字了

   ConcurrentMap<Key, Graph> graphs = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .makeComputingMap((Key key) -> createExpensiveGraph(key));

   ConcurrentMap<Key, Graph> graphs = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .makeComputingMap(this::createExpensiveGraph);

王才
2023-03-14

AtomicLong实际上不是一个沉重的对象。对于较重的对象,我会考虑使用惰性代理,并在需要时向该代理提供lambda以创建对象。

class MyObject{
    void doSomething(){}
}

class MyLazyObject extends MyObject{
    Funktion create;
    MyLazyObject(Funktion create){
        this.create = create;
    }
    MyObject instance;
    MyObject getInstance(){
        if(instance == null)
            instance = create.apply();
        return instance;
    }
    @Override void doSomething(){getInstance().doSomething();}
}

public long addTo(String key, long value) {
  return map.putIfAbsent( key, new MyLazyObject( () -> new MyObject(0) ) );
}
禄烨然
2023-03-14

更新 2015-08-01

下面描述的< code > computeifaxine 方法确实已经添加到Java SE 8中。语义似乎非常接近预发布版本。

此外,computeIfAbsent 以及一大堆新的默认方法已添加到 Map 接口中。当然,地图通常不支持原子更新,但新方法为 API 增加了相当大的便利性。

您尝试的做法非常合理,但不幸的是,它不适用于当前版本的< code>ConcurrentMap。然而,一项改进正在进行中。新版本的并发库包括< code>ConcurrentHashMapV8,其中包含一个新方法< code > computeifaxine 。这几乎可以让你做你想做的事情。使用这种新方法,您的示例可以重写如下:

public long addTo(String key, long value) {
    return map.computeIfAbsent( key, () -> new AtomicLong(0) ).addAndGet(value);
}

有关ConcurrentHashMapV8的更多信息,请参阅DougLea在并发兴趣邮件列表上的初始公告线程。线程下面的几个消息是一个后续消息,它显示了一个与您所尝试的非常相似的示例。(不过,请注意旧的lambda语法。该消息毕竟来自2011年8月。)这里是最近的javadoc for<code>ConcurrentHashMapV8</code>。

这项工作打算集成到Java 8中,但据我所知,它还没有。此外,这仍在进行中,名称和规格可能会更改等。

 类似资料:
  • 我在Java8中遇到了一个问题,在使用cast时,它不允许我收集对象。 我得到了编译器错误: 错误:(71,23)java:不兼容类型:推理变量T的边界不兼容等式约束:java。util。列出下限:java。lang.反对 任何帮助都将不胜感激。 更新:

  • 温馨提示:该项目已开源,用户在项目基础上的所有操作、修改须进行标记,并保留原项目版权说明。 羊驼!羊驼!前方惊现羊驼 ! 羊驼! 是一个开源的轻量级树状 CMS 系统。它基于 php + mysql 开发,并使用 b2core  为底层MVC架构。 可以方便快速的配置出个人、企业网站。 如果你是打算开发一个内容网站,或者是开发一款基于PHP的应用,羊驼!CMS 都会是个不错的开始,它可以帮你节省构

  • 我有三个活动,每个都有一个按钮。Act1与btn1,Act2与btn2,Act3与btn3。我有另一个活动作为主活动,有三个图像视图:ImageView1、imageView2和imageView3,所有这些最初都是不可见的。我希望这样,当我在act1中单击btn1时,MainActivity中的imageView1将可见,而当再次单击btn1,ImageView 1将再次不可见。与imageVi

  • 引用脚本的内容: ; 该脚本使用 HM VNISEdit 脚本编辑器向导产生 !include "LogicLib.nsh" ; 安装程序初始定义常量 !define PRODUCT_NAME "猪猪番薯主题包" !define PRODUCT_VERSION "1.3" !define PRODUCT_PUBLISHER "猪猪番薯论坛" !define PRODUCT_UNINST_KE

  • 嗨,我是Hadoop的新手,我发现在Java map reduce中使用SkipBadRecord类可以跳过任何输入格式的badrecords,所以我只想知道在Pig和Hive中是如何实现的?