如何在基于java模式匹配的地图中找到密钥?

如何在基于java模式匹配的地图中找到密钥?,java,regex,Java,Regex,我想在地图中找到模式匹配的关键点 Ex:- Map<String, String> map = new HashMap<String, String>(); map.put("address1", "test test test"); map.put("address2", "aaaaaaaaaaa"); map.put("fullname&qu

我想在地图中找到模式匹配的关键点

Ex:-   
    Map<String, String> map = new HashMap<String, String>();
    map.put("address1", "test test test");
    map.put("address2", "aaaaaaaaaaa");
    map.put("fullname", "bla bla");
Ex:-
Map Map=newhashmap();
地图放置(“地址1”,“测试”);
地图放置(“地址2”,“AAAAAAAA”);
地图放置(“全名”、“布拉布拉布拉”);
从上面的映射中,我想得到前缀为“address”的键的值。因此,在本例中,输出应该是前两个结果(“address1”和“address2”)

如何动态地实现这一点?

类似这样的内容:

    for (Entry<String, String> entry : map.entrySet()) {
        if (entry.getKey().startsWith("address")) {
            // do stuff with entry
        }
    }
for(条目:map.entrySet()){
if(entry.getKey().startsWith(“地址”)){
//用入口做东西
}
}

您可以抓取地图的
键集,然后过滤以仅获取以“address”开头的键,并将有效键添加到新的键集

对于Java 8,它的详细程度要低一些:

Set<String> set = map.keySet()
                     .stream()
                     .filter(s -> s.startsWith("address"))
                     .collect(Collectors.toSet());
Set Set=map.keySet()
.stream()
.filter(s->s.startsWith(“地址”))
.collect(收集器.toSet());

您必须循环通过钥匙组并匹配模式

for(String key : map.keySet()) {
   if(! key.startsWith("address")) {
       continue;
   }

   // do whatever you want do as key will be match pattern to reach this code.
}

如果您有Java 8功能,类似这样的功能应该可以工作:

    Set<String> addresses = map.entrySet()
                               .stream()
                               .filter(entry -> entry.getKey().startsWith("address"))
                               .map(Map.Entry::getValue)
                               .collect(Collectors.toSet());
Set addresses=map.entrySet()
.stream()
.filter(entry->entry.getKey().startsWith(“地址”))
.map(map.Entry::getValue)
.collect(收集器.toSet());

如果您不需要高性能,浏览地图上的所有键(
map.entrySet
)以获得与您的模式匹配的键就足够了

如果您需要良好的性能,我用来解决此类问题的解决方案是使用内存中的数据库,如H2:将数据放入内存表中,在键上创建唯一索引,在以下两种情况下,您将获得良好的性能:

  • 获取与键关联的值(
    从in_mem_表中选择值,其中键=?”
    ),hashmap的经典用法
  • 获取与“键模式”关联的值(
    从“地址%”等键所在的“内存”表中选择值)

我创建了一个接口

import java.util.Map;

@FunctionalInterface
public interface MapLookup {
    <V> List<V> lookup(String regularExpression, Map<String,V> map);
}
或者这可能太过分了。不过,我可以看到它的重复使用

对于希望使用java8之前版本的用户:

    public class PreJava8MapLookup implements MapLookup {
    @Override
    public <V> List<V> lookup(String regularExpression, Map<String, V> map) {
        Matcher matcher = Pattern.compile(regularExpression).matcher("");
        Iterator<String> iterator = map.keySet().iterator();
        List<V> values = new ArrayList<>();
        while(iterator.hasNext()){
            String key = iterator.next();
            if(matcher.reset(key).matches()){
                values.add(map.get(key));
            }
        }
        return values;
    }
}
public类PreJava8MapLookup实现MapLookup{
@凌驾
公共列表查找(字符串正则表达式、映射){
Matcher Matcher=Pattern.compile(regularExpression.Matcher)(“”);
迭代器迭代器=map.keySet().Iterator();
列表值=新的ArrayList();
while(iterator.hasNext()){
String key=iterator.next();
if(matcher.reset(key.matches()){
add(map.get(key));
}
}
返回值;
}
}

一种方法是创建一个函数,在所有地图中搜索以地址开头的键,但这会消除地图的优势,因为目标可能是快速。 另一种方法是创建一个列表或数组,其中包含所有以address开头的键,但这仅在您只需要以address开头的键时才有价值


现在,您需要能够搜索任何东西还是只搜索特定的东西?你需要地图还是可以是数组或列表之类的东西?

我遇到了类似的需求,并尝试为这样的数据结构实现POC。我得出的结论是,以某种方式对数据进行分区要实际得多:)

然而,如果您真的想实现这样的东西,那么您需要一个更类似于trie树的结构。这是我得到的(我很抱歉,因为代码是Scala的,但是它可以很容易地被修改,如果你下定决心,你可能会完成它并使它可用)


只使用
get()
是没有办法的,你必须使用类似
entrySet()
的东西并循环键来进行正则表达式匹配你使用的是什么版本的Java?都很好,但我认为这会给出
值,而不是
键,原始问题询问了前缀为“address”的键的值,这些键应该是
entry.getKey()…
而不是
entry.getValue()…
public static void main(String[] args){

    Map<String, Integer> map = new HashMap<>();
    map.put("foo",3);
    map.put("bar",42);
    map.put("foobar",-1);

    MapLookup lookup = new MapLookupImpl();

    List<Integer> values = lookup.lookup("\\woo\\w*",map);

    System.out.println(values);
}
[-1, 3]
    public class PreJava8MapLookup implements MapLookup {
    @Override
    public <V> List<V> lookup(String regularExpression, Map<String, V> map) {
        Matcher matcher = Pattern.compile(regularExpression).matcher("");
        Iterator<String> iterator = map.keySet().iterator();
        List<V> values = new ArrayList<>();
        while(iterator.hasNext()){
            String key = iterator.next();
            if(matcher.reset(key).matches()){
                values.add(map.get(key));
            }
        }
        return values;
    }
}
    package component.datastructure

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

class RegExpLookup[T] {

  private val root = new mutable.HashMap[Char, Node]

  def put(key: String, value: T): Unit = {
    addNode(key.toCharArray, 0, root, value)
    println(root.toString)
  }

  private def addNode(key: Array[Char], charIdx: Int,
                      currentRoot: mutable.Map[Char, Node], value: T): Unit = {
    if (charIdx < key.length - 1) {
      if (currentRoot.contains(key(charIdx))) {
        addNode(key, charIdx + 1, currentRoot(key(charIdx)).nodeRoot, value)
      } else {
        val node = Node(null, new mutable.HashMap[Char, Node])
        currentRoot.put(key(charIdx), node)
        addNode(key, charIdx + 1, node.nodeRoot, value)
      }
    } else {
      currentRoot.put(key(charIdx), Node(value, null))
    }
  }

  private def getAll(lastNode: Node, buffer: ArrayBuffer[T]): Unit = {
    if (lastNode.value != null)
      buffer.append(lastNode.value.asInstanceOf[T])
    if (lastNode.nodeRoot != null)
      lastNode.nodeRoot.values.foreach(e => {
        getAll(e, buffer)

      })

  }

  def get(key: String): Iterable[T] = {
    val t = findLastNode(key.toCharArray, 0, root)
    println("getting from " + root)
    val isLast = t._2
    if (isLast) {
      val v = t._1.value
      if (v != null)
        return List(v.asInstanceOf[T])
      else
        return null
    } else {
      val buffer = new ArrayBuffer[T]()
      getAll(t._1, buffer)
      return buffer.toList
    }
  }

  private def findLastNode(key: Array[Char], charIdx: Int,
                           root: mutable.Map[Char, Node]): (Node, Boolean) = {
    if (charIdx < key.length - 2 && (key(charIdx + 1) != '*')) {
      return (root(key(charIdx)), false)
    } else if (charIdx < key.length - 1) {
      return findLastNode(key, charIdx + 1, root(key(charIdx)).nodeRoot)
    } else
      return (root(key(charIdx)), true)
  }
}

case class Node(value: Any, private[datastructure] val nodeRoot: mutable.HashMap[Char, Node]) {

}
class MySpec extends PlaySpec {

  val map = new RegExpLookup[String]()

  "RegExpLookup" should {

    "put a bunch of values and get all matching ones" in {
      map.put("abc1", "123")
      map.put("abc2", "456")
      map.put("abc3", "789")
      val result = map.get("abc*")
      println(result)
      val s = result.toSet
      assert(s.contains("123"))
      assert(s.contains("456"))
      assert(s.contains("789"))
    }

    "put a single value and get it by exact key" in {
      map.put("abc", "xyz")
      val result = map.get("abc")
      println(result)
      assert(result.head.equals("xyz"))
    }
  }

}