程序猿成长之路之数据挖掘篇——距离公式介绍

news2024/11/26 0:34:50

上一篇介绍了朴素贝叶斯,那么这次讲讲距离公式

什么是距离公式

用自己的话来说距离公式就是判断两个属性(参数)相似度的度量公式,比如以两点间距离为例,A地经纬度为(110.9802,120.9932),B地经纬度为(110.9980,120.8280), C地经纬度为(98.0232,110.9829),那么我们可以得出|AB| < |AC|,也就是说A地离B地的距离更近。再举个例子,同一个学校里有不同的学生,学生又有性别、年龄、兴趣爱好等属性,那么如果两个学生之间的性别、年龄、兴趣爱好等属性越接近,那么这两个学生的距离公式所得出的结果也就越小,两个学生也就越相像。

为什么要有距离公式

距离公式存在的意义在于不仅可以计算两个数值属性的相似度(如同上述的经纬度信息),而且可以计算两个度量甚至标称属性的相似度。
* 数值、度量、标称、二元属性的定义详见: 数据挖掘介绍https://blog.csdn.net/qq_31236027/article/details/137046475
而计算相似度的意义在于之后可以区分不同对象的差异性,从而方便后续的挖掘关联规则并进行相似度推荐。

常见的距离计算方式(后续会拓展展开讲讲)

数值属性的距离计算公式:

  1. 欧几里得距离公式
  2. 曼哈顿距离公式
  3. 上确界距离(切比雪夫距离)公式
  4. 闵可夫斯基距离公式

序数属性的距离计算方式:
若设置Rif 表示第i个对象的第f个属性的值,且该属性为序数属性,该属性有n个可选的值,且每个值的权重相同,又设置Zif为序数距离计算后的值,则有:
Zif = (Rif - 1) / n

标称属性的距离计算公式:
d(i,j) = (p-m) / p ⇒ 个人理解为不同的属性占全部属性的比例。

二元属性的距离计算公式:

  1. Jaccard公式:sim(i,j) = q / q + r + s, d(i,j) = 1 - sim(i,j)
  2. 余弦相似度公式

混合属性的距离计算公式:
sim(i,j) = Σ(f=1, p) δij(f) * sim(i,j) (f) / Σ(f=1,p) δij(f)
怎么理解呢?后续会详细展开讲讲

欧几里得距离公式

假设有A地和B地,经纬度分别为(x1,y1)和(x2,y2)
那么AB间的距离d(A,B) = |AB| = (√该符号表示根号) √(x1-x2)^2 + (y1-y2)^2
也就是取不同数值属性的差的平方和再进行开根运算。得出的结果就是欧几里得距离公式得出的结果

曼哈顿距离公式

假设有A地和B地,经纬度分别为(x1,y1)和(x2,y2)
那么AB间的距离d(A,B) = |AB| = |x1-x2| + |y1 -y2|
也就是取不同数值属性的差的绝对值和。得出的结果就是曼哈顿距离得出的结果

闵可夫斯基距离公式

假设有A地和B地,经纬度分别为(x1,y1)和(x2,y2)
那么AB间的距离d(A,B) = √(h) |x1- x2|^h + |y1-y2|^h = (Σ(f=1,2) |xAf- xBf| ^h)^1/h
也就是取不同数值属性的差的h次方求和再进行开h次方根运算。得出的结果就是闵可
夫斯基距离公式得出的结果

上确界距离(切比雪夫距离)公式

假设有A地和B地,经纬度分别为(x1,y1)和(x2,y2)
那么AB间的距离d(A,B) = limh->∞((Σ(f=1,2) |xAf- xBf| ^h)^1/h = max(f=1, p) |xAf- XBf|
也就是取闵可夫斯基距离公式的极限,约等于差异最大的属性的差值。
上确界距离公式推导可见:https://blog.csdn.net/qq_31236027/article/details/106763491

序数属性的距离计算

例如:现在有一个属性叫成绩,其中有3个值,分别为好,一般,差,那么该属性可以进行序数化,也就是用数字代替文本求距离。(假设权重一致)
P(好) = (3-1)/(3-1) = 1, #前一个(3-1) 表示的是值的位置,后一个(3-1)是为了将值映射到[0.0,1.0]上
P(一般) = (2-1)/(3-1) = 0.5
P(差) = (1-1) / (3-1) = 0
之后计算距离就方便了,可以利用数值属性的距离计算公式进行计算。

标称属性的距离计算

标称属性计算就很简单,求出不相同的属性的数量去除以对象A和B之间所有标称属性
数量就是标称属性的距离。

二元属性的距离计算

Jaccard距离计算公式:
假设对象i属性值为1且对象j属性值也为1的二元属性数量为q,对象i属性值为0但对象j属性值为1的二元属性数量为s,对象i属性值为1但是对象j属性值为0的二元属性数量为r,对象i和对象j属性值均为0的属性数量为t,那么有:
在这里插入图片描述
sim(i,j) = q(对象i和对象j属性的值都为1) + t 对象i和对象j属性的值都为0) / (q+r+s+t)
又有:对象i和对象j属性值均为0的属性没有意义,所以上述公式可以优化成以下公式:
sim(i,j) = q / q + r + s = 1- d(i,j) #该公式为jaccard公式。

余弦相似度公式:
sim(i,j) = |A ∩ B| / |A ∪ B|

混合属性的距离计算

sim(i,j) = Σ(f=1, p) δij(f) * sim(i,j) (f) / Σ(f=1,p) δij(f)
就是可以简单理解为标称、序数、数值、二元属性的距离计算完成后进行求和之后取平均值,

相关代码

各位小伙伴可以借鉴以下,以下是距离公式的java实现

package diffUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 距离公式
 * @author zygswo
 *
 */
public class DiffUtils {
	
	/**
	 * 测试对象
	 * @author zygswo
	 *
	 */
	class TestObject {
		@Override
		public String toString() {
			return "TestObject [name=" + name + ", age=" + age + ", gender=" + gender + ", myHobby=" + myHobby
					+ ", myDream=" + myDream + "]";
		}
		public List<MyHobby> getMyHobby() {
			return myHobby;
		}
		public TestObject setMyHobby(List<MyHobby> myHobby) {
			this.myHobby = myHobby;
			return this;
		}
		public String getName() {
			return name;
		}
		public TestObject setName(String name) {
			this.name = name;
			return this;
		}
		public int getAge() {
			return age;
		}
		public TestObject setAge(int age) {
			this.age = age;
			return this;
		}
		public String getGender() {
			return gender;
		}
		public TestObject setGender(String gender) {
			this.gender = gender;
			return this;
		}
		String name;
		
		@Elem(weight=0.1,type = ElemType.NUMBER)
		int age;
		
		@Elem(weight=0.2,type = ElemType.XUSHU,list={"男","女"})
		String gender;
		
		@Elem(weight=0.3)
		List<MyHobby> myHobby;
		
		@Elem(weight=0.4)
		List<String> myDream;
		
		public TestObject(String name, int age, String gender) {
			super();
			this.name = name;
			this.age = age;
			this.gender = gender;
		}
		
		public TestObject(String name, int age, String gender,List<MyHobby> myHobby) {
			this(name,age,gender);
			this.myHobby = myHobby;
		}
		
		public TestObject(String name, int age, String gender,List<MyHobby> myHobby, List<String> myDreams) {
			this(name,age,gender);
			this.myHobby = myHobby;
			this.myDream = myDreams;
		}
		
		
	}
	
	/**
	 * 欧几里得距离公式
	 * @param obj1
	 * @param obj2
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static <T> double EuclidDistance(T obj1, T obj2) 
			throws IllegalArgumentException, IllegalAccessException {
		Class<?> cls = obj1.getClass();
		Field[] fs = cls.getDeclaredFields();
		double result = 0.0;
		for (Field f:fs) {
			f.setAccessible(true);
			Object xVal = f.get(obj1);
			Object yVal = f.get(obj2);
			long x = xVal.hashCode();
			long y = yVal.hashCode();
			System.out.println("x = " + x);
			System.out.println("y = " + y);
			result += EuclidDistance(x,y,1.0);
			System.out.println("result = " + result);
		}
		return Math.sqrt(result);
	}
	
	/**
	 * 计算相似度
	 * @param obj1
	 * @param obj2
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static <T> T calculDiff(T obj1, T ... obj2) 
			throws IllegalArgumentException, IllegalAccessException {
		double min = 1.0;
		T mostLikelyItem = null;
		for (T obj : obj2) {
			double res = Double.parseDouble(calculDiff(obj1, obj));
			System.out.println("res = " + res);
			if (res < min) {
				min = res;
				mostLikelyItem = obj;
			}
		}
		return mostLikelyItem;
	}
	
	/**
	 * 计算相似度
	 * @param obj1
	 * @param obj2
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	@SuppressWarnings("rawtypes")
	public static <T> String calculDiff(T obj1, T obj2) 
			throws IllegalArgumentException, IllegalAccessException {
		Class<?> cls = obj1.getClass();
		Class<?> cls2 = obj2.getClass();
		if (!cls.getName().equalsIgnoreCase(cls2.getName())) {
			throw new IllegalArgumentException("参数类型不匹配");
		}
		Field[] fs = cls.getDeclaredFields();
		double result = 0.0, restWeight = 1.0; //result=相似度,restWeight=剩余权重
		int blankWeightFieldCount = 0; //elem中权重为空的field数量
		//计算变量数量
		for (Field f0:fs) {
			Elem elem0 = f0.getAnnotation(Elem.class);
			if (elem0 != null) {
				if (elem0.weight() == 1) {
					blankWeightFieldCount++;
				} else {
					restWeight = restWeight - elem0.weight();
					restWeight = Double.parseDouble(
							String.format("%.2f",restWeight)
					);
				}
				if (restWeight < 0) {
					throw new IllegalArgumentException("权重总量分配超过1");
				}
			}
		}
		for (Field f:fs) {
			f.setAccessible(true);
			Object xVal = f.get(obj1);
			Object yVal = f.get(obj2);
			Elem elem = f.getAnnotation(Elem.class);
			if (elem == null) {
				continue;
			}
			if (xVal instanceof ArrayList && yVal instanceof ArrayList) {
				Object[] objList1 = ((ArrayList)xVal).toArray();
				Object[] objList2 = ((ArrayList)yVal).toArray();
				Object[] objList3 = new Object[objList1.length + objList2.length];
				/**
				 * 1. 数组复制
				 * 2. 数组排序
				 * 3. 利用jaccard公式计算相似度(相异性 为 1- 相似度)
				 */
				//数组进行复制
				System.arraycopy(objList1, 0, objList3, 0, objList1.length);
				System.arraycopy(objList2, 0, objList3, objList1.length, objList2.length);
				//数组排序
				Arrays.sort(objList3);
				int same = 0,total = objList3.length;
				for (int i = 0; i < objList3.length-1;i++) {
					Object pre = objList3[i];
					Object after = objList3[i+1];
					if (pre.equals(after)) {
						same++;		//重复的元素++
						total--;	//两个重复了,减去一个
						i++;
					}
				}
				//简单规则,jaccard公式计算相似度(相异性 为 1- 相似度)
				System.out.println("same = "  + same);
				System.out.println("total = "  + total);
				if (total != 0) {
					result += elem.weight() * (1 - same / (total * 1.0));
					System.out.println("result = " + result);
				}
			} else {
				double temp = calcDiff(f,xVal,yVal);
				System.out.println("temp = " + temp);
				/**
				 * 如果field权重为1,那么相似度 = temp /权重为1的所有field数量
				 * 否则就按照权重进行分配。
				 * 例如:
				 */
				if (elem.weight() > 0 && elem.weight() < 1) {
					temp = temp * elem.weight();
				} else {
					temp = temp * restWeight / blankWeightFieldCount;
				}
//				System.out.println("temp = " + temp);
				result += temp;
				System.out.println("result = " + result);
			}
		}
		return String.format("%.2f",result);
	}
	
	private static double calcDiff(Field f,Object xVal, Object yVal) {
		long x = xVal.hashCode();
		long y = yVal.hashCode();
		System.out.println("x = " + x);
		System.out.println("y = " + y);
		Elem elem = f.getAnnotation(Elem.class);
		List<String> elemVals = Arrays.asList(elem.list());
		double temp = 0.0;
		switch(elem.type()) {
			case NUMBER:
				if (x == y) {
					temp =  0;
				} else {
					double max = x > y ? x : y;
					temp = Math.sqrt(EuclidDistance(x,y,1.0))/(max * 1.0);
					temp = Double.parseDouble(String.format("%.2f", temp));
				}
				break;
			case ERYUAN: temp = (x == y) ? 0 : 1; break;
			case BASIC: temp = (x == y) ? 0 : 1;break;
			case XUSHU:
				int xIndex = elemVals.indexOf(xVal);
				int yIndex = elemVals.indexOf(yVal);
				System.out.println("xIndex = " + xIndex);
				System.out.println("yIndex = " + yIndex);
				if (xIndex == -1) {
					throw new IllegalArgumentException("第一个对象的序数参数" + f.getName() + "值不匹配");	
				}
				if (yIndex == -1) {
					throw new IllegalArgumentException("第二个对象的序数参数" + f.getName() + " 值不匹配");	
				}
				temp = Math.abs(xIndex - yIndex)/(elemVals.size() * 1.0); break;
			default:
				break; 
		}
		return temp;
	}

	/**
	 * 欧几里得距离公式
	 * @param x0
	 * @param x1
	 */
	private static double EuclidDistance(long x0, long x1,double weight){
		return Math.pow(Math.abs(x0-x1), 2) * weight;
	}
	
	/**
	 * 数据统计
	 */
	private static <T extends TestObject> List<MyStatistics> getMyStatistics(T... objList){
		Map<String, List<MyHobby>> hobbyMap = new ConcurrentHashMap<>();
		Map<String, Integer> countMap = new ConcurrentHashMap<>();
		List<MyStatistics> myStatistics = new ArrayList<>();
		for (T obj: objList) {
			String gender = obj.getGender();
			countMap.put(gender,countMap.get(gender)== null ? 1 : countMap.get(gender) + 1);
			if (hobbyMap.get(gender) == null) {
				List<MyHobby> myHobbyList = obj.getMyHobby();
				hobbyMap.put(gender,myHobbyList);
				System.out.println(gender);
				System.out.println(myHobbyList.toString());
			} else {
				List<MyHobby> mapList = hobbyMap.get(gender);
				List<MyHobby> myHobbyList = obj.getMyHobby();
				for (MyHobby myHobby: myHobbyList) {
					if (!mapList.contains(myHobby)) {
						mapList.add(myHobby);
					}
				}
				hobbyMap.put(gender,mapList);
			}
		}
		for (String gender: hobbyMap.keySet()) {	
			myStatistics.add(new MyStatistics().setGender(gender)
					.setMyHobbyList(hobbyMap.get(gender)).setNbPerson(countMap.get(gender)));
		}
 		return myStatistics;
	}

	
	public static void main(String[] args) {
		DiffUtils util = new DiffUtils();
		MyHobby h1 = new MyHobby("爬山");
		MyHobby h2 = new MyHobby("音乐");
		MyHobby h3 = new MyHobby("看书");
		MyHobby h4 = new MyHobby("追剧");
		MyHobby h5 = new MyHobby("摄影");
		MyHobby h6 = new MyHobby("户外运动");
		List<MyHobby> list1 = new ArrayList<>();
		list1.add(h1);
		list1.add(h2);
		list1.add(h3);
		list1.add(h4);
		list1.add(h5);
		List<MyHobby> list2 = new ArrayList<>();
		list2.add(h1);
		list2.add(h2);
		list2.add(h3);
		list2.add(h4);
		List<MyHobby> list3 = new ArrayList<>();
		list3.add(h6);
		list3.add(h2);
		List<String> characterList1 = new ArrayList<>();
		characterList1.add("坚强");
		characterList1.add("自信");
		characterList1.add("乐观");
		List<String> characterList2 = new ArrayList<>();
		characterList2.add("坚强");
		characterList2.add("自信");
		characterList2.add("乐观");
		TestObject obj1 = util.new TestObject("zyg",18,"男",list1,characterList1);
		TestObject obj2 = util.new TestObject("zcx",15,"女",list2,characterList2);
		TestObject obj3 = util.new TestObject("zyg",22,"男",list3,characterList1);
		System.out.println(getMyStatistics(obj1,obj2,obj3));
		try {
			double res = Double.parseDouble(calculDiff(obj1,obj2));
			System.out.println("相似度:" + (1-res));
			System.out.println(calculDiff(obj1,obj2,obj3));
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

—————————————— 有问题的话评论区见——————————————

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1669438.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++04STL部分复习

1、deque list vector概括&#xff1a; /* deque :双端队列容器 底层数据结构&#xff1a;动态开辟的二维数组&#xff0c;一维数组从2开始&#xff0c;以2倍的方式进行扩容&#xff0c;每次扩容后&#xff0c;原来的第二维的数组 从新的第一堆数组下表的oldsize/2开始存放&am…

XYCTF - web

目录 warm up ezMake ezhttp ezmd5 牢牢记住&#xff0c;逝者为大 ezPOP 我是一个复读机 ezSerialize 第一关 第二关 第三关 第一种方法&#xff1a; 第二种方法&#xff1a; ez?Make 方法一&#xff1a;利用反弹shell 方法二&#xff1a;通过进制编码绕过 ε…

EasyImage2.0 图床源码

EasyImage2.0 是一个简单图床的源码&#xff0c;它支持以下功能&#xff1a; 1. API接口 2. 登录后才能上传图片 3. 设置图片质量 4. 压缩图片大小 5. 添加文字或图片水印 6. 设定图片的宽度和高度 7. 将上传的图片转换为指定的格式 8. 限制上传图片的最小宽度和高度 …

《软件方法(下)》8.3.3 泛化的一些重点讨论(202405更新)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 8.3 建模步骤C-2 识别类的关系 8.3.3 泛化的一些重点讨论 8.3.3.1 子集的不相交和完整 泛化是集合关系&#xff0c;在建模泛化关系时&#xff0c;我们对泛化关系中的子类&#xff0…

JavaEE初阶-多线程5

文章目录 一、线程池1.1 线程池相关概念1.2 线程池标准类1.3 线程池工厂类1.4 实现自己的线程池 二、定时器2.1 java标准库中的定时器使用2.2 实现一个自己的定时器2.2.1 定义任务类2.2.2 定义定时器 一、线程池 1.1 线程池相关概念 池这个概念在计算机中比较常见&#xff0c…

极验4图标方向点选验证码

验证码如下如所示&#xff0c;提供了三个方向剪头。根据剪头顺序&#xff0c;点击大图中图标的方向完成验证。 经过我们的努力&#xff0c;正确率达到了90%左右。下面提供了验证码识别的代码。 import base64 import requests import datetime from io import BytesIO from PI…

Linux-软件安装--tomcat的安装

tomcat的安装 1、下载tomcat安装包2.移动到自己想要解压的目录3、解压文件夹4、启动tomcat5、查看tomcat进程6、查看日志7、通过浏览器访问成功8、停止tomecat服务8.1运行tomcat的bin目录中提供的停止服务的脚本文件shutdcwn.sh8.2结束tomcat进程1、下载tomcat安装包 本篇文章…

蓝海创业商机小吃配方项目,日入200+ ,小白可上手,图文创作转现快

小吃技术销售&#xff0c;一单价格从几元到几百元不等&#xff0c;行业竞争相对较小&#xff0c;是一个相对冷门的领域。只需一部手机&#xff0c;就可以发布图文并茂的内容&#xff0c;配上背景音乐&#xff08;BGM&#xff09;&#xff0c;即使是对视频剪辑不熟悉的新手&…

【WEEK11】 【DAY6】Employee Management System Part 7【English Version】

2024.5.11 Saturday Continued from 【WEEK11】 【DAY5】Employee Management System Part 6【English Version】 Contents 10.8. Delete and 404 Handling10.8.1. Modify list.html10.8.2. Modify EmployeeController.java10.8.3. Restart10.8.4. 404 Page Handling10.8.4.1. …

如何取消格式化SD卡并恢复丢失的数据?

在相机中格式化SD卡后&#xff0c;您将丢失卡上的所有文件。如果有恢复形成操作的选项&#xff0c;您可以轻松取回文件。然而&#xff0c;相机或任何其他设备中没有这样的选项。它无法直接取消格式化相机SD卡&#xff0c;但您仍然可以从格式化的SD卡中恢复文件。 为什么格式化后…

excel常见图表大全

Excel图表是一种以图形形式呈现数据的工具&#xff0c;它将数字和统计信息转化为直观的视觉元素&#xff0c;如线图、柱状图、饼图等。这些图表可以帮助人们更容易地理解数据的趋势、关系和模式。 使用场景 Excel图表广泛应用于各个领域&#xff0c;包括&#xff1a; 商务分…

服装定制|基于SSM+vue的服装定制系统的设计与实现(源码+数据库+文档)

服装定制系统 目录 基于SSM&#xff0b;vue的服装定制系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户后台管理模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xf…

基于Springboot的村庄果园预售系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的村庄果园预售系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

2024情感聊天赛道,al工具制做,视频一分钟一条,日入500+

在这个领域&#xff0c;我们可以利用AI技术快速制作情感文章和闲聊内容。基本原理是结合热门创意文案&#xff0c;通过AI生成情感聊天短视频&#xff0c;然后在各大网站进行独家代理&#xff0c;这个领域的竞争相对较小&#xff0c;可以说是一片蓝海。 项 目 地 址 &#xff…

【目标检测论文解读复现NO.38】基于改进YOLOv8模型的轻量化板栗果实识别方法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

【机器学习】LoFTR:革命性图像特征批评技术等领跑者

LoFTR&#xff1a;革命性图像特征匹配技术的领跑者 一、引言二、LoFTR技术的创新之处三、LoFTR技术的实现原理四、LoFTR技术的代码实例五、结语 一、引言 在3D计算机视觉领域&#xff0c;图像特征匹配技术一直是研究的热点和难点。随着技术的不断发展&#xff0c;传统的特征检…

电子学会C/C++编程等级考试2024年03月(八级)真题解析

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;道路 N个以 1 … N 标号的城市通过单向的道路相连:。每条道路包含两个参数&#xff1a;道路的长度和需要为该路付的通行费&#xff08;以金币的数目来表示&#xff09; Bob and Alice 过去住在城市 1.在…

ACE框架学习4

目录 ACE Proactor框架 异步I/O工厂类 ACE_Handler类 前摄式Acceptor-Connector类 ACE_Proactor类 ACE Streams框架 ACE_Model类 ACE_Streams类 ACE Proactor框架 ACE Proactor框架实现了proactor模式&#xff0c;也就是异步网络模式&#xff0c;允许事件驱动…

并行执行线程资源管理方式——《OceanBase 并行执行》系列 3

在某些特定场景下&#xff0c;由于需要等待线程资源&#xff0c;并行查询会遇到排队等待的情况。本篇博客将介绍如何管理并行执行线程资源&#xff0c;以解决这种问题。 《OceanBase并行执行》系列的内容分为七篇博客&#xff0c;本篇是其中的第三篇。前2篇如下&#xff1a; 一…

容器组件:Column ,Row(HarmonyOS学习第四课【4.1】)

容器组件-Column Column 容器组件是沿垂直方向布局的容器。该组件从APIVersion7开始支持从API version 9开始&#xff0c;该接口支持在ArkTs,卡片中使用。其可以包含子组件 Column(value?: {space?: string | number}) 参数 space 参数类型string | number 是否必填&am…