【已解决】Java中,判断:集合中是否包含指定元素(模糊匹配)比如权限中的user:list或者是user:*这种判断

背景描述

在工作中,有时候,我们需要对list中是否包含了指定元素进行判断,但是,有时候又需要支持模糊匹配,这个时候怎么办呢?

比如权限,我们知道,权限不仅可以配置完整的路径,也可以配置通配符。比如,系统管理员角色直接返回的权限是*。子公司A的管理员返回的是:departmentA:*的权限。子公司A的人事权限是:hrA:*。你自己登录系统后,返回的权限是:userA:view这个权限。类似这样的,一个人不止是只有一个权限。多个权限,那么这种情况下,想要判断集合中是否包含了指定元素,而且还需要模糊匹配,使用Java语言怎么写呢?凯哥(个人公众号:凯哥Java),接下来就讲讲怎么实现的。

思路:

  1. 简单匹配,如果list中包含了指定的元素(element)的时候,就直接返回;

  2. 如果list不包含,就开始模糊匹配

    循环list中每个元素:

2.1. 如果元素中不包含【*】的时候,只需要简单的将list循环出来的数据和需要对比的元素进行equals比较即可;

2.2:如果元素中包含了【*】的时候,就要进行第三步:深入匹配

3.深入匹配

将list循环出来的每个数据与需要匹配的元素每个字符进行比较。

具体代码如下:

一、定义函数接口,用来判断集合中是否包含指定元素

java 复制代码
import java.util.List;
import java.util.function.BiFunction;

/**
 * 函数式接口:判断集合中是否包含指定元素(模糊匹配)
 *
 * <p>  参数:集合、元素  </p>
 * <p>  返回:是否包含  </p>
 *
 * @author click33
 * @since 1.35.0
 */
@FunctionalInterface
public interface SaHasElementFunction extends BiFunction<List<String>, String, Boolean> {

}

二、开始进行对集合中是否包含了指定元素进行判断:

java 复制代码
/**
	 * 判断:集合中是否包含指定元素(模糊匹配)
	 */
	public SaHasElementFunction hasElement = (list, element) -> {

		// 空集合直接返回false
		if(list == null || list.size() == 0) {
			return false;
		}

		// 先尝试一下简单匹配,如果可以匹配成功则无需继续模糊匹配
		if (list.contains(element)) {
			return true;
		}

		// 开始模糊匹配
		for (String patt : list) {
			if(SaFoxUtil.vagueMatch(patt, element)) {
				return true;
			}
		}

		// 走出for循环说明没有一个元素可以匹配成功
		return false;
	};

简单匹配不成功后,开始模糊匹配:

java 复制代码
/**
	 * 字符串模糊匹配
	 * <p>example:
	 * <p> user* user-add   --  true
	 * <p> user* art-add    --  false
	 * @param patt 表达式
	 * @param str 待匹配的字符串
	 * @return 是否可以匹配
	 */
	public static boolean vagueMatch(String patt, String str) {
		// 两者均为 null 时,直接返回 true
		if(patt == null && str == null) {
			return true;
		}
		// 两者其一为 null 时,直接返回 false
		if(patt == null || str == null) {
			return false;
		}
		// 如果表达式不带有*号,则只需简单equals即可 (这样可以使速度提升200倍左右)
		if( ! patt.contains("*")) {
			return patt.equals(str);
		}
		// 深入匹配
		return vagueMatchMethod(patt, str);
	}	

元素中,不包含【*】,进行深入匹配:

java 复制代码
/**
	 * 字符串模糊匹配
	 *
	 * @param pattern /
	 * @param str    /
	 * @return /
	 */
	private static boolean vagueMatchMethod( String pattern, String str) {
		int m = str.length();
		int n = pattern.length();
		boolean[][] dp = new boolean[m + 1][n + 1];
		dp[0][0] = true;
		for (int i = 1; i <= n; ++i) {
			if (pattern.charAt(i - 1) == '*') {
				dp[0][i] = true;
			} else {
				break;
			}
		}
		for (int i = 1; i <= m; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (pattern.charAt(j - 1) == '*') {
					dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
				} else if (str.charAt(i - 1) == pattern.charAt(j - 1)) {
					dp[i][j] = dp[i - 1][j - 1];
				}
			}
		}
		return dp[m][n];
	}

完整的匹配代码:

java 复制代码
/**
	 * 判断:集合中是否包含指定元素(模糊匹配)
	 */
	public SaHasElementFunction hasElement = (list, element) -> {

		// 空集合直接返回false
		if(list == null || list.size() == 0) {
			return false;
		}

		// 先尝试一下简单匹配,如果可以匹配成功则无需继续模糊匹配
		if (list.contains(element)) {
			return true;
		}

		// 开始模糊匹配
		for (String patt : list) {
			if(SaFoxUtil.vagueMatch(patt, element)) {
				return true;
			}
		}

		// 走出for循环说明没有一个元素可以匹配成功
		return false;
	};
	
	
	
	/**
	 * 字符串模糊匹配
	 * <p>example:
	 * <p> user* user-add   --  true
	 * <p> user* art-add    --  false
	 * @param patt 表达式
	 * @param str 待匹配的字符串
	 * @return 是否可以匹配
	 */
	public static boolean vagueMatch(String patt, String str) {
		// 两者均为 null 时,直接返回 true
		if(patt == null && str == null) {
			return true;
		}
		// 两者其一为 null 时,直接返回 false
		if(patt == null || str == null) {
			return false;
		}
		// 如果表达式不带有*号,则只需简单equals即可 (这样可以使速度提升200倍左右)
		if( ! patt.contains("*")) {
			return patt.equals(str);
		}
		// 深入匹配
		return vagueMatchMethod(patt, str);
	}
	
	
	
	/**
	 * 字符串模糊匹配
	 *
	 * @param pattern /
	 * @param str    /
	 * @return /
	 */
	private static boolean vagueMatchMethod( String pattern, String str) {
		int m = str.length();
		int n = pattern.length();
		boolean[][] dp = new boolean[m + 1][n + 1];
		dp[0][0] = true;
		for (int i = 1; i <= n; ++i) {
			if (pattern.charAt(i - 1) == '*') {
				dp[0][i] = true;
			} else {
				break;
			}
		}
		for (int i = 1; i <= m; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (pattern.charAt(j - 1) == '*') {
					dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
				} else if (str.charAt(i - 1) == pattern.charAt(j - 1)) {
					dp[i][j] = dp[i - 1][j - 1];
				}
			}
		}
		return dp[m][n];
	}

阅读更多文章👉:凯哥个人博客

相关推荐
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨2 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404192 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
P.H. Infinity3 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
爱吃土豆的程序员3 小时前
java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
xml·java·cdata