如何在Scala中使用ConcurrentHashMap computeIfAbsent()

时间:2016-04-24 18:53:37

标签: scala concurrenthashmap

我在Scala中使用ConcurrentHashMap,我想使用computeIfAbsent()方法,但无法弄清楚第二个参数的语法。有人能告诉我什么是正确的语法?

运行以下代码时

val data = new ConcurrentHashMap[String, LongAdder]

data.computeIfAbsent("bob", k: String => new LongAdder()).increment()

我收到以下错误

Type mismatch, expected: Function[_ >: String, _ <: LongAdder], actual: (String) => Any

提前感谢你

弗朗西斯

2 个答案:

答案 0 :(得分:5)

问题是您正在使用java.util.concurrent.ConcurrentHashMapjava.util.function.Function接受computeIfAbsent()作为scala.Function1的参数,而不是您传递给java.util.function.Function的{​​{1}}。

由于scala不像Java那样支持功能接口的lambda转换(至少没有-Xexperimental flag),你可以通过明确地实现val data = new ConcurrentHashMap[String, LongAdder] val adderSupplier = new java.util.function.Function[String, LongAdder]() { override def apply(t: String): LongAdder = new LongAdder() } data.computeIfAbsent("bob", adderSupplier).increment() 来解决这个问题:

object FunctionConverter {
  implicit def scalaFunctionToJava[From, To](function: (From) => To): java.util.function.Function[From, To] = {
    new java.util.function.Function[From, To] {
      override def apply(input: From): To = function(input)
    }
  }
}

import FunctionConverter._
val data = new ConcurrentHashMap[String, LongAdder]()
data.computeIfAbsent("bob", (k: String) => new LongAdder()) // <- implicit conversion applied here

或者,如果您更频繁地需要这个,您可以编写实用程序转换函数甚至是隐式转换:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class Stacker
  extends JFrame
  implements KeyListener
{
  int iteration = 1;
  static double time = 200.0D;
  static int last = 0;
  static int m = 10;
  static int n = 20;
  JLabel[][] b;
  static int[] length = { 5, 5 };
  static int layer = 19;
  static int[] deltax = new int[2];
  static boolean press = false;
  static boolean forward = true;
  static boolean start = true;

  public static void main(String[] args)
  {
    System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
    new Stacker();
  }

  public Stacker()
  {
    setDefaultCloseOperation(3);
    this.b = new JLabel[m][n];
    setLayout(new GridLayout(n, m));
    for (int y = 0; y < n; y++) {
      for (int x = 0; x < m; x++)
      {
        this.b[x][y] = new JLabel(" ");
        this.b[x][y].setBackground(Color.white);
        add(this.b[x][y]);
        this.b[x][y].setEnabled(true);
        this.b[x][y].setOpaque(true);
        this.b[x][y].setBorder(BorderFactory.createLineBorder(Color.GRAY));
        this.b[x][y].setPreferredSize(new Dimension(40, 30));
      }
    }
    setFocusable(true);
    addKeyListener(this);
    pack();
    setVisible(true);
    go();
  }

  public void go()
  {
    int tmp = 0;
    Component temporaryLostComponent = null;
    do
    {
      if (forward) {
        forward();
      } else {
        back();
      }
      if (deltax[1] == 10 - length[1]) {
        forward = false;
      } else if (deltax[1] == 0) {
        forward = true;
      }
      draw();
      try
      {
        Thread.sleep(time);
      }
      catch (InterruptedException e)
      {
        e.printStackTrace();
      }
    } while (!

      press);
    if (layer > 12) {
      time = 150 - (this.iteration * this.iteration * 2 - this.iteration);
    } else {
      time -= 2.2D;
    }
    this.iteration += 1;
    layer -= 1;
    press = false;
    tmp = check();
    length[0] = length[1];
    length[1] = tmp;
    if ((layer == -1) && (length[1] > 0))
    {
      JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");
      System.exit(0);
    }
    if (length[1] <= 0)
    {
      JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line " + (18 - layer) + "!");
      System.exit(0);
    }
    last = deltax[1];
    start = false;
    go();
  }

  public int check()
  {
    if (start) {
      return length[1];
    }
    if (last < deltax[1])
    {
      if (deltax[1] + length[1] - 1 <= last + length[0] - 1) {
        return length[1];
      }
      return length[1] - Math.abs(deltax[1] + length[1] - (last + length[0]));
    }
    if (last > deltax[1]) {
      return length[1] - Math.abs(deltax[1] - last);
    }
    return length[1];
  }

  public void forward()
  {
    deltax[0] = deltax[1];
    deltax[1] += 1;
  }

  public void back()
  {
    deltax[0] = deltax[1];
    deltax[1] -= 1;
  }

  public void draw()
  {
    for (int x = 0; x < length[1]; x++) {
      this.b[(x + deltax[0])][layer].setBackground(Color.white);
    }
    for (int x = 0; x < length[1]; x++) {
      this.b[(x + deltax[1])][layer].setBackground(Color.BLUE);
    }
  }

  public void keyPressed(KeyEvent e)
  {
    if (e.getKeyCode() == 32) {
      press = true;
    }
  }

  public void keyReleased(KeyEvent arg0) {}

  public void keyTyped(KeyEvent arg0) {}
}

答案 1 :(得分:3)

如果启用scala> val data = new java.util.concurrent.ConcurrentHashMap[String, Int] data: java.util.concurrent.ConcurrentHashMap[String,Int] = {} scala> data.computeIfAbsent("bob", _.size) res0: Int = 3 标志,则可以使用scala匿名函数表示法:

Function

请注意,您仍然无法传递常规scala scala> val f: String => Int = _.size f: String => Int = <function1> scala> data.computeIfAbsent("bob", f) <console>:13: error: type mismatch; found : String => Int required: java.util.function.Function[_ >: String, _ <: Int] data.computeIfAbsent("bob", f) ^

scala> def a(s: String): Int = s.size
a: (s: String)Int

scala> data.computeIfAbsent("bob", a)
res3: Int = 3

但是eta扩展会起作用

HRESULT CaptureManager::doSelectInputUsingCrossbar(std::wstring deviceName, long input) 
{


IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
IBaseFilter* pSrc = NULL;

ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pClassEnum = NULL;
IMoniker *pMoniker = NULL;
bool bCameraFound = false;
IPropertyBag *pPropBag = NULL;


bool crossbarSet = false;

HRESULT hr = S_OK;

if (!(input == PhysConn_Video_Composite || input == PhysConn_Video_SVideo))
{
    return S_FALSE;
}



// Create the Filter Graph Manager.
 hr = CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (SUCCEEDED(hr))
{
    // Create the Capture Graph Builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
        (void **)&pBuilder);
    if (SUCCEEDED(hr))
    {
        pBuilder->SetFiltergraph(pGraph);
    }
    else return hr;
}
else return hr;

//////////////////////////


// chooses the default camera filter

hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
    IID_ICreateDevEnum, (void **)&pDevEnum);
if (FAILED(hr))
{

    return E_FAIL;
}

// Create an enumerator for video capture devices.

if (FAILED(pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0)))
{

    return E_FAIL;
}

if (pClassEnum == NULL)
{
    CheckHR(hr, "Class enumerator is null - no input devices detected?");
    pDevEnum->Release();
    return E_FAIL;
}



while (!bCameraFound && (pClassEnum->Next(1, &pMoniker, NULL) == S_OK))
{

    HRESULT hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
    if (FAILED(hr))
    {
        pMoniker->Release();
        continue;  // Skip this one, maybe the next one will work.
    }

    // Find the description or friendly name.
    VARIANT varName;
    VariantInit(&varName);
    hr = pPropBag->Read(L"Description", &varName, 0);
    if (FAILED(hr))
    {
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    }
    if (SUCCEEDED(hr))
    {
        if (0 == wcscmp(varName.bstrVal, deviceName.c_str()))
        {
            pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc);
            bCameraFound = true;
            break;
        }//if
        VariantClear(&varName);
    }

    pPropBag->Release();
    pMoniker->Release();
}//while

pClassEnum->Release();
pDevEnum->Release();

if (!bCameraFound)//else
{
    CheckHR(hr, "Error: Get device Moniker, No device found");
    goto done;
}



hr = pGraph->AddFilter(pSrc, L"video capture adapter");
if (FAILED(hr))
{
    CheckHR(hr, "Can't add capture device to graph");
    goto done;
}


///////////////


IAMCrossbar *pxBar = NULL;
hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pSrc, IID_IAMCrossbar, (void **)&pxBar);
if (FAILED(hr))
{
    hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSrc, IID_IAMCrossbar, (void **)&pxBar);

    if (FAILED(hr))
    {
        CheckHR(hr, "Failed to get crossbar filter");
        goto done;
    }
}//if
else
{
    CheckHR(hr, "Failed to get crossbar (capture)");
    goto done;
}

LONG lInpin, lOutpin;
hr = pxBar->get_PinCounts(&lOutpin, &lInpin);

BOOL IPin = TRUE; LONG pIndex = 0, pRIndex = 0, pType = 0;

while (pIndex < lInpin)
{
    hr = pxBar->get_CrossbarPinInfo(IPin, pIndex, &pRIndex, &pType);

    if (pType == input)
    {
        break;
    }

    pIndex++;
}

BOOL OPin = FALSE; LONG pOIndex = 0, pORIndex = 0, pOType = 0;

while (pOIndex < lOutpin)
{
    hr = pxBar->get_CrossbarPinInfo(OPin, pOIndex, &pORIndex, &pOType);

    if (pOType == PhysConn_Video_VideoDecoder)
    {
        break;
    }

    pIndex++;
}

hr = pxBar->Route(pOIndex, pIndex);




done:
SafeRelease(&pPropBag);
SafeRelease(&pMoniker);
SafeRelease(&pxBar);


SafeRelease(&pGraph);
SafeRelease(&pBuilder);
SafeRelease(&pSrc);

return hr;