Unity Jobsystem ECS
简介
随着ECS的加入,Unity基本上改变了软件开发方面的大部分方法。ECS的加入预示着OOP方法的结束。随着实体组件系统ECS的到来,我们在Unity开发中曾使用的大量实践方法都必须进行改变以适应ECS,也许不少人需要些时间适应ECS的使用,但是ECS会对游戏性能的提升产生很大作用。
面向对象编程是一个很好的编程模式,OOP非常容易掌握和易于理解,尤其适合初学者。OOP的最大优点是它的可访问性,开发者可以在几乎没有任何相关知识的情况下创建类并维护编写的代码。然而OOP方法带有严重的缺点,它会给总体性能带来不好的影响,因为OOP方法很难避免出现重复的代码,造成一定程度上的性能开销,而且OOP虽然简单,但是却很依赖引用。
面向对象编程是基于特定对象的概念实现的,对象的种类由类的实例定义,它们通过互相交互来构建程序。对象可以包含属性和方法等形式的数据。
ECS实体组件系统的方法和OOP不同,它的数据和行为/方法是明确分离的,这样能大大提高内存使用效率,从而提高性能。
现在对于Unity而言,ECS还处于早期阶段,有很大的发展空间,但是开发者已经可以开始使用ECS。本文将讲解ECS的常见方法,Hybrid ECS和Pure ECS,并且介绍ECS的实现方法、语法以及如何开始使用ECS。
ECS方法
对于ECS,我们会更多谈论实体(Entity),而不是游戏对象。或许你会觉得实体和游戏对象没有太大区别,因为你可以将实体视为组件的容器(Container)。但是,如果你深入研究的话,会发现二者区别很大,实体其实只是特定组件的句柄。
OOP和ECS所提到的“组件”是否相同?不,这二者并不一样。在ECS出现前,我们通常将附加到游戏对象上的MonoBehaviour视为组件。MonoBehaviour包含数据和行为,它的数据来自所有变量,行为来自用于定义和调用游戏对象的函数。ECS是不同的,因为实体和组件都没有任何行为逻辑,它们只包含数据。
所有逻辑都保存在Managers/Systems中,它会获取一组实体,然后根据分组实体所包含的数据来执行所请求的行为。这意味着现在,不是所有实体都会处理自己的行为,而是所有实体行为都会在同一位置进行处理。
要完全理解为什么ECS方法比旧OOP方法的速度更快,你需要了解内存管理的相关知识。在OOP方法中,数据不会被组织起来,而是会分散再整个内存中,这是因为使用了自动内存管理功能。
自动内存管理功能介绍
像C#这种语言,内存的分配和释放过程是通过垃圾收集器自动完成的。该过程开始后,Mono平台会从操作系统请求特定容量的内存,并使用该部分内存来生成代码可使用的堆内存空间。该堆空间随着代码需要使用更多内存而逐渐增大。如果不再需要之前声明的内存,内存会释放回操作系统,堆的大小也会随之减小,这便是垃圾回收器的工作方式。
对于之后的内存分配,如果大小合适的话,垃圾回收器会使用之前用于保存数据并在释放后产生的剩余“间隙”。
因此,将数据从内存移动到缓存需要消耗较多性能,因为必须先找到引用才可以进行移动。
对于内存管理而言,ECS更加优化,因为ECS的数据会根据类型进行保存,而不是根据数据的分配时间。试想一下,一个商店根据商品的上架顺序放置商品,另一个商店根据商品的分类放置商品,你认为哪个商店的做法更好?
ECS性能更高效的另一个原因是,由于数据已明确地分离出来,ECS只会缓存相关数据。这是什么意思呢?
当使用OOP时,无论何时访问游戏对象,即使只需要一个特定属性,都必须缓存该对象的所有属性,该做法会对性能产生很大影响,因为缓存这些类型的话,会导致原生系统和托管系统之间的交互,而这样做就会产生垃圾,导致垃圾回收的发生。
Hybrid ECS
目前想纯粹使用ECS来编写一个完整的游戏还不太现实,因为部分Unity功能还未支持ECS,但是这个原因不会阻止我们使用ECS。
Hybrid ECS允许我们将ECS逻辑结合到现有的项目中,利用ECS的优点,而且不会影响还未支持ECS的功能的使用。
Hybrid ECS会和helper类一同工作,例如:Game Object Entity,它会将游戏对象转换为实体,并将附带的MonoBehaviour转换为组件。
我们编写的C#脚本派生自MonoBehaviour,它只包含数据但没有行为,然后我们将这些MonoBehaviour附加到带有Game Object Entity的游戏对象上。
我们的行为会放到Manager/System中,该类必须派生自ComponentSystem。我们不需要将该类附加到场景中的游戏对象,因为Unity会检测到该类并自动执行它。
在System类中,我们将通过定义它附带的组件来将Entity定义为struct。我们不会使用Update函数,而是使用OnUpdate函数来获取实体,并在实体中进行迭代并执行行为。
ECS Solar System (Hybrid)
我们已经了解到实体组件系统是什么,现在来研究一下实际案例。
如前文所所述,学习使用ECS对一些人而言很难,因为必须改变自己编写程序的方法。希望下面部分内容能够帮助你轻松理解该过程。
我们将使用Hybrid ECS编写一个小型宇宙,因为Hybrid ECS非常容易掌握,希望看完本案例后,你不会对ECS感到恐惧,而是更自信地尝试使用ECS。
项目准备
本文中使用的版本是Unity 2018.2.0.2,首先从资源包管理器获取Entities资源包。打开Window >> PackageManager,找到Entities进行安装。
安装完成后,Console中会出现报错内容,但这是正常现象。我们还要将脚本运行时版本从.Net 3.5改为.Net 4.x,方法是打开Build Settings >> Player Settings,修改脚本运行时版本。
预制件
Hybrid ECS拥有能将MonoBehaviour转换为组件的helper类,我们来仔细研究一下。
首先我们为星球、行星、椭圆形和月球创建大量预制件。
从上图中可以看到,该预制件就像普通预制件一样,没有什么特别之处。预制件上带有Transform、Mesh Filter、Mesh Renderer和Mesh Collider。
该预制件上添加了Game Object Entity组件。该组件不是自定义编写的脚本,而是前面提到的helper类,它将把普通游戏对象转换为实体。
Planet Comonent组件,代码如下:
using UnityEngine;
public class PlanetComponent : MonoBehaviour
{
public float rotationSpeed;
public float orbitDuration;
public OrbitalEllipse orbit;
}
Components Job用来保存数据,所以在该函数中没有其它内容。下面列出了所有需要的组件,这些组件就不进行太多讲解。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoonComponent : MonoBehaviour {
public float movementSpeed;
public GameObject parentPlanet;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OrbitalElipseComponent : MonoBehaviour {
public float xExtent;
public float yExtent;
public GameObject parent;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StarComponent : MonoBehaviour {
[Range(0f, 100f)] public float twinkleFrequency;
}
这样组件和预制件就设置好了,是不是非常简单。
HybridECSSolarSystem
在我们通过创建组件来处理所有数据之前,如果仔细阅读前文,就知道现在我们需要处理行为。
我们将添加新C#脚本,命名为HybridECSSolarSystem,我们不会将该脚本附加到任何对象上,实际上它甚至不是MonoBehaviour,它派生自ComponentSystem。
Unity会在内部检测并执行该脚本,请记得添加using Unity.Entities声明。我们将在该类的开始定义Stars、Planets和Moons的struct,前面提到实体是组件分组的句柄,所以Stars类型的实体是附带StarComponent和MeshRenderer组件的所有实体。
或许你还注意到,我们没有Update()函数,而是使用了protected override void OnUpdate(),派生自ComponentSystem的每个类都需要拥有OnUpdate()函数,我们的实体行为将在该函数中执行。
仔细观察OnUpdate()函数中第一个foreach循环会发现,该循环获取了所有Stars类型的实体,然后循环处理每个实体。我们通过检查依赖starComponent.twinkleFrequency实体的Random.Range来获得随机性。
using UnityEngine;
using Unity.Entities;
public class HybridECSSolarSystem : ComponentSystem
{
struct Stars
{
public StarComponent starComponent;
public MeshRenderer renderer;
}
struct Planets
{
public PlanetComponent planetComponent;
public Transform transform;
}
struct Moons
{
public Transform transform;
public MoonComponent moonComponent;
}
protected override void OnUpdate()
{
foreach (var starEntity in GetEntities<Stars>())
{
int timeAsInt = (int)Time.time;
if(Random.Range(1f, 100f) < starEntity.starComponent.twinkleFrequency)
{
starEntity.renderer.enabled = timeAsInt % 2 == 0;
}
}
foreach (var planetEntity in GetEntities<Planets>())
{
planetEntity.transform.Rotate(Vector3.up * Time.deltaTime * planetEntity.planetComponent.rotationSpeed, Space.Self);
planetEntity.transform.position = planetEntity.planetComponent.orbit.Evaluate(Time.time / planetEntity.planetComponent.orbitDuration);
}
foreach (var moonEntity in GetEntities<Moons>())
{
Vector3 parentPos = moonEntity.moonComponent.parentPlanet.transform.position;
Vector3 desiredPos = (moonEntity.transform.position - parentPos).normalized * 5f + parentPos;
moonEntity.transform.position = Vector3.MoveTowards(moonEntity.transform.position, desiredPos, moonEntity.moonComponent.movementSpeed);
moonEntity.transform.RotateAround(moonEntity.moonComponent.parentPlanet.transform.position, Vector3.up, moonEntity.moonComponent.movementSpeed);
}
}
}
我们没有通过以前的方法使用Update函数,而是执行了System类中的Update,这就是在使用Hybrid ECS时的区别。
虽然我们已经完成将游戏对象转换为实体所需的操作,但我们还需要一个类来实例化银河系,现在进入下一部分。
HybridECSInstantiator
HybridECSInstantiator类的内容非常简单明了,不必进行过多赘述。我们在实例化整个太阳系的场景中,设置了一组变量用来创建游戏对象。
我们通过使用处理对象位置的onUnitSphere和UniverseRadius,将宇宙的大致结构视为球形。通过计算生成椭圆形,然后使用LineRenderer组件进行绘制,我们便得到了椭圆形轨道。
我们使用了HybridECSSolarSystem.cs类中的Ellipse.Evaluate()函数实现了行星的移动。
对于每个对象,不管是Star还是Planet,我们只是实例化这些对象,设置它们的组件并放置到合适的位置。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HybridECSInstatiator : MonoBehaviour
{
[Header("General Settings:")]
[SerializeField] float universeRadius;
[Header("Sun:")]
[SerializeField] GameObject sunPrefab;
[SerializeField] Vector3 sunPosition;
[Header("Moon:")]
[SerializeField] GameObject moonPrefab;
[SerializeField] float minMoonMovementSpeed;
[SerializeField] float maxMoonMovementSpeed;
[Header("Stars:")]
[SerializeField] GameObject starPrefab;
[SerializeField] float minStarsize;
[SerializeField] float maxStarsize;
[SerializeField] int starsAmount;
[SerializeField] [Range(0, 100)] float minTwinkleFrequency;
[SerializeField] [Range(0, 100)] float maxTwinkleFrequency;
[Header("Orbital Elipses:")]
[SerializeField] int elipseSegments;
[SerializeField] float elipseWidth;
[SerializeField] GameObject orbitalElipsePrefab;
[Header("Planets:")]
[SerializeField] List<Planet> planets = new List<Planet>();
static HybridECSInstatiator instance;
public static HybridECSInstatiator Instance { get { return instance; } }
GameObject sun;
void Awake()
{
instance = this;
PlaceSun();
PlaceStars();
PlacePlanets();
}
#region Sun
void PlaceSun()
{
sun = Instantiate(sunPrefab, sunPosition, Quaternion.identity);
GameObject sunParent = new GameObject();
sunParent.name = "Sun";
sun.transform.parent = sunParent.transform;
}
#endregion
#region Stars
void PlaceStars()
{
GameObject starParent = new GameObject();
starParent.name = "Stars";
for (int i = 0; i < starsAmount; i++)
{
GameObject currentStar = Instantiate(starPrefab);
currentStar.transform.parent = starParent.transform;
currentStar.GetComponent<StarComponent>().twinkleFrequency = Random.Range(minTwinkleFrequency, maxTwinkleFrequency);
float randomStarScale = Random.Range(minStarsize, maxStarsize);
currentStar.transform.localScale = new Vector3(randomStarScale, randomStarScale, randomStarScale);
currentStar.transform.position = Random.onUnitSphere * universeRadius;
currentStar.SetActive(true);
}
}
#endregion
#region OrbitalElipses
void DrawOrbitalElipse(LineRenderer line, OrbitalEllipse ellipse)
{
Vector3[] drawPoints = new Vector3[elipseSegments + 1];
for (int i = 0; i < elipseSegments; i++)
{
drawPoints[i] = ellipse.Evaluate(i / (elipseSegments - 1f));
}
drawPoints[elipseSegments] = drawPoints[0];
line.useWorldSpace = false;
line.positionCount = elipseSegments + 1;
line.startWidth = elipseWidth;
line.SetPositions(drawPoints);
}
#endregion
#region Planets
void PlacePlanets()
{
GameObject planetParent = new GameObject();
planetParent.name = "Planets";
for (int i = 0; i < planets.Count; i++)
{
GameObject currentPlanet = Instantiate(planets[i].planetPrefab);
currentPlanet.transform.parent = planetParent.transform;
currentPlanet.GetComponent<PlanetComponent>().rotationSpeed = planets[i].rotationSpeed;
currentPlanet.GetComponent<PlanetComponent>().orbitDuration = planets[i].orbitDuration;
currentPlanet.GetComponent<PlanetComponent>().orbit = planets[i].orbit;
GameObject currentElipse = Instantiate(orbitalElipsePrefab, sunPosition, Quaternion.identity);
currentElipse.transform.parent = sun.transform;
DrawOrbitalElipse(currentElipse.GetComponent<LineRenderer>(), planets[i].orbit);
if(planets[i].hasMoon)
{
GenerateMoon(currentPlanet);
}
}
}
#endregion
#region Moons
void GenerateMoon(GameObject planet)
{
GameObject moonParent = new GameObject();
moonParent.name = "Moons";
GameObject currentMoon = Instantiate(moonPrefab);
currentMoon.transform.parent = moonParent.transform;
currentMoon.GetComponent<MoonComponent>().movementSpeed = Random.Range(minMoonMovementSpeed, maxMoonMovementSpeed);
currentMoon.GetComponent<MoonComponent>().parentPlanet = planet;
}
#endregion
}
[System.Serializable]
public class OrbitalEllipse
{
public float xExtent;
public float yExtent;
public float tilt;
public Vector3 Evaluate(float _t)
{
Vector3 up = new Vector3(0, Mathf.Cos(tilt * Mathf.Deg2Rad), -Mathf.Sin(tilt * Mathf.Deg2Rad));
float angle = Mathf.Deg2Rad * 360f * _t;
float x = Mathf.Sin(angle) * xExtent;
float y = Mathf.Cos(angle) * yExtent;
return up * y + Vector3.right * x;
}
}
[System.Serializable]
public class Planet
{
public GameObject planetPrefab;
public OrbitalEllipse orbit;
public bool hasMoon;
[Header("Movement Settings:")]
public float rotationSpeed;
public float orbitDuration;
}
这样一个小型的宇宙便实现了!
相关文章:
Unity Jobsystem ECS
简介随着ECS的加入,Unity基本上改变了软件开发方面的大部分方法。ECS的加入预示着OOP方法的结束。随着实体组件系统ECS的到来,我们在Unity开发中曾使用的大量实践方法都必须进行改变以适应ECS,也许不少人需要些时间适应ECS的使用,…...
Java中创建线程有哪几种方式
1.继承Thread类 总结:通过继承 Thread 类,重写 run() 方法,而不是 start() 方法 Thread 类底层实现 Runnable 接口类只能单继承 接口可以多继承2.实现Runnable接口 总结:通过实现 Runnable 接口,实现 run() 方法,依然…...
C++【string类用法详细介绍string类模拟实现解析】
文章目录string 类用法介绍及模拟实现一、string介绍二、string类常用接口1. string类对象的常见构造接口2.string类对象的常见容量接口3.string类对象的常见修改接口4. string类对象的常见访问及遍历接口5.string其他接口1.不常用查找接口2.字符替换3.字符串拼接4.字符串排序5…...
常见的开发模型和测试模型
软件的生命周期软件开发阶段的生命周期需求分析->计划->设计->编码->测试->运维软件测试阶段的生命周期需求分期->测试计划->测试设计与开发->执行测试->测试评估开发模型瀑布模型可以看到,这个模型和我们上面的软件开发生命周期很相似采用的是线性…...
印度和印度尼西亚有什么关系吗?
印度和印度尼西亚,这两个国家很多人都比较熟悉。因为两国都是人口大国,而且经济总量也比较高,在全球还是有很大影响的。不过很多人刚看到这两个国家的时候,都会觉得这两个国家肯定有什么关系,要不然国名也不会这么像。…...
单调栈(C/C++)
目录 1. 单调栈的定义 2. 单调栈的常见用途 3. 案例分析 3.1 暴力解法 3.2 单调栈 4. 单调栈总结 1. 单调栈的定义 单调栈顾名思义,就是栈内的元素是单调的。根据栈内元素的单调性的不同,可以分为: 单调递增栈:栈内元素是单…...
算法设计与智能计算 || 专题一: 算法基础
专题一: 算法基础 文章目录专题一: 算法基础1. 算法的定义及特点1.1 算法的基本特征1.2 算法的基本要素1.3 算法的评定2 算法常见执行方法2.1 判断语句2.2 循环语句2.3 综合运用3. 计算复杂度4. 代码的重用5. 类函数的定义与使用5.1 定义类5.2 调用类函数1. 算法的定义及特点 …...
用javascript分类刷leetcode13.单调栈(图文视频讲解)
239. 滑动窗口最大值 (hard) 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums [1,…...
英语基础语法学习(B站英语电力公司)
1. 句子结构 五大基本句型: 主谓主谓宾主谓宾宾主谓宾宾补主系表 谓语: 一般来说,谓语是指主语发出的动作。(动词)但是很多句子是没有动作的,但是还是必须要有谓语。(此时需要be动词&#x…...
【计算机网络】网络层IP协议
文章目录一、认识IP协议二、IP协议头部格式三、IP地址划分1. IP地址分类2. 子网划分四、IP地址数量危机1. IP地址的数量限制2. NAT技术五、私网IP和公网IP六、路由1. 认识路由2. 路由表生成算法一、认识IP协议 IP协议是Internet Protocol(互联网协议)的…...
Eclipse快捷键大全
编辑类快捷键Ctrl1: 快速修复(最经典的快捷键, 可以解决很多问题, 比如import类、try catch包围等)CtrlShiftF: 格式化当前代码CtrlShiftM: 添加类的import导入CtrlShiftO: 组织类的导入(既有CtrlShiftM的作用,又可以去除没用的导入, 一般用这个导入包)CtrlY: 重做(与CtrlZ相反…...
JavaScript 高级2 :构造函数和原型 d331702016e84f54b3594ae05e0eeac
JavaScript 高级2 :构造函数和原型 Date: January 16, 2023 Text: 构造函数和原型、继承、ES5中的新增方法 目标 能够使用构造函数创建对象 能够说出原型的作用 能够说出访问对象成员的规则 能够使用 ES5新增的一些方法 构造函数和原型 概述 在典型的 OOP 的…...
maven-war-plugin插件 overlays maven-war-plugin翻译
说明 翻译maven-war-plugin插件的部分内容 官方地址为:https://maven.apache.org/plugins/maven-war-plugin/index.html Overview 概述 Introduction 介绍 Apache Maven WAR Plugin apache maven war 插件 The WAR Plugin is responsible for collecting all artifa…...
【数据结构】初识二叉树(二叉树的入门知识)
初识二叉树一、树概念及结构1、树的概念2、树的相关概念3、树的表示4、树在实际中的运用(表示文件系统的目录树结构)二、二叉树概念及结构1、概念2、特殊的二叉树3、二叉树的性质4、二叉树的存储结构三、结语一、树概念及结构 1、树的概念 树是一种非线…...
RV1126笔记三十二:基于 FastDeploy 在 RV1126 上的部署示例(RV1126 上部署 YOLOv5 检测模型测试)
若该文为原创文章,转载请注明原文出处。 FastDeploy是一款全场景、易用灵活、极致高效的AI推理部署工具, 支持云边端部署。提供超过 🔥160+ Text,Vision, Speech和跨模态模型📦开箱即用的部署体验,并实现🔚端到端的推理性能优化。包括 物体检测、字符识别(OCR)、…...
JVM垃圾回收——G1垃圾收集器
目录 一、什么是G1垃圾收集器 二、G1垃圾收集器的内存划分 三、G1垃圾收集器的收集过程 四、G1收集器的优缺点 五、G1收集器的JVM参数配置 一、什么是G1垃圾收集器 Garbage First(简称G1)收集器是垃圾收集器技术发展史上里程碑式的成果,它摒弃了传统垃圾收集器的…...
C语言深度剖析:关键字
C语言深度剖析:关键字C语言深度剖析:关键字前言定义与声明(补充内容)最宏大的关键字-auto最快的关键字-register关键字static被冤枉的关键字-sizeof整型在内存中的存储原码、反码、补码大小端补充理解变量内容的存储和取出为什么都是补码整型取值范围关于…...
聊一聊过度设计!
文章目录什么是过度设计?过度设计的坏处如何避免过度设计充分理解问题本身保持简单小步快跑征求其他人的意见总结新手程序员在做设计时,因为缺乏经验,很容易写出欠设计的代码,但有一些经验的程序员,尤其是在刚学习过设…...
程序员在小公司(没有大牛,人少)怎么成长?
大多数小公司都是创业公司,所以它们有着非常独特的“创业心态”。所谓创业心态通常表现为关注快速增长,竭尽所能让公司盈利,或者达成其他一些迫切目标。 在这样一家公司工作的软件开发人员,你极有可能要身兼多职,不能…...
【Fastdfs实战】在本地如何将文件上传到Linux虚拟机
作者:狮子也疯狂 专栏:《Fastdfs连续剧》 坚持做好每一步,幸运之神自然会驾凌在你的身上 目录一. 🦁 前言二. 🦁 上传原理Ⅰ. 🐇 原理图解Ⅱ. 🐇 传输原理三. 🦁 实战演示Ⅰ. &…...
ERP 系统的应用对企业财务会计信息系统内部控制的影响
(一)对企业的财务信息数据进行实时和动态管理传统的财务会计信息系统一般都是采用单一的软件系统,所以在信息的传递及处理上常常不能满足企业的需要,信息与其他部门存在不对称及滞后的现象。而ERP 系统是通过有效的技术手段将企业的各种分散的数据进行完…...
智慧物联网源码带手机端源码 物联网系统源码
在智慧工厂领域,智慧城市领域,都需要对设备进行监控。比如工厂需要对周围环境温度、湿度、气压、电压,灯的开关进行监控。这时候就需要物联网平台来进行管理。 推荐一个基于java开发的物联网平台,前端HTML带云组态、可接入视频监…...
AI绘画进军三次元,有人用它打造赛博女友?(diffusion)
目录0 写在前面1 AI绘画技术飞跃2 效果展示3 环境配置3.1 下载基础模型3.2 更新.NET和模型3.3 下载绘画模型3.4 启动项目3.5 标签配置4 结语0 写在前面 机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理&a…...
计算机网络高频知识点
目录 一、http状态码 二、浏览器怎么数据缓存 三、强缓存与协商缓存 1、强缓存 2、协商缓存 四、简单请求与复杂请求 五、PUT 请求类型 六、GET请求类型 七、GET 和 POST 的区别 八、跨域 1、什么时候会跨域 2、解决方式 九、计算机网络的七层协议与五层协议分别指…...
谈谈前端性能优化-面试版
前言 当我们去面试的时候,很大概率会被面试官问这么一个问题:你有尝试过对项目做性能优化吗?或者你了解哪些性能优化的方法?听到这个问题的你可能是这样的: 似曾相识但又说不清楚,往往只能零散地说出那么几…...
JAVA连接数据库——JDBC的简单使用
JDBC即Java数据库连接.用来实现Java程序对数据库增删查改。 为了对接Java程序和数据库,java.sql提供了很多api包含在java.sql和javax.sql里面 结构: DriverManager接口: 每一个数据库的驱动程序都必须去到DriverManager注册,生成一个Connection Conn…...
Pandas数据查询
Pandas数据查询 Pandas查询数据的几种方法 df.loc方法,根据行、列的标签值查询 df.iloc方法,根据行、列的数字位置查询 df.where方法 df.query方法 .loc既能查询,又能覆盖写入,强烈推荐! Pandas使用df.loc查询数据…...
NLP-统计词频之处理停用词
前言 本文是该专栏的第1篇,后面会持续分享NLP的各种干货知识,值得关注。 一般来说,自然语言处理(NLP)就是开发能够理解人类语言的应用程序或者应用服务。 举个例子,如Facebook News Feed这种社交网站推送,它的算法知道你的兴趣是自然语言处理,就会推送相关的广告或者…...
sort 定制排序规则(配合functools.cmp_to_key())
sort 定制排序规则(配合functools.cmp_to_key()) 配合例题学习 题目链接:179. 最大数 题目大意:给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 注意&a…...
【华为OD机试模拟题】用 C++ 实现 - 内存池(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明内存池题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:…...
那些企业网站做的较好/网络营销咨询公司
我用两台LinuxLinuxA IP:192.168.10.101LinuxB IP:192.168.10.102首先我们在LinuxA上挂载光驱和安装FTP服务器然后安装FTP服务器(在同一台上,也就是LinuxA上)修改FTP的主配置文件(添加一句话anon…...
网站建设实战教程/2022年十大网络流行语发布
在正文之前,我想问大家一个问题:问:亲,你有基础吗?答: 有啊,你说前端吗? 不就是HTML,JS,CSS 吗? so easy~问: oh-my-zsh... 好吧,那问题来了,挖掘机技术哪家强... 开玩笑。 现在才是问题的正内…...
福建自适应网站建设/北京seo案例
当我们去github上克隆代码仓库的时候,一般有两种选择,一种是https协议,一种是ssh协议。这也是最常用的两种协议了。 HTTPS协议(推荐) 优点: 对新手友好,使用简单,clone的时候只需…...
互站网源码商城/电商网站建设教程
入一行,要先知一行 ”;我们来看看web前端开发职位 无论什么门派都要做到的一些基本工作职责 首先,你必须是一个合格的“页面仔”,这个叫法不好听,但很生动; 我们都知道,所有呈现的内容都是基于…...
wordpress 用法/百度搜索榜排名
application对象 application对象负责提供应用程序在服务器中运行时的一些全局信息,常用的方法有getMimeType和getRealPath等。 运用实例:网页访问计数器。 <% page language"java" import"java.util.*" pageEncoding"UTF-8…...
wordpress git升级/网站推广的途径和方法
如果您只想使用CSS3,甚至不需要使用任何jQuery / Javascript。只需在您的CSS中执行此操作:.confirm_selection {-webkit-transition: text-shadow 0.2s linear;-moz-transition: text-shadow 0.2s linear;-ms-transition: text-shadow 0.2s linear;-o-tr…...