【用户画像】标签任务开发流程(源码之实体类、工具类、配置文件、DAO层)
文章目录
- 一 代码实现
- 0 开发主线
- 1 实体类
- (1)TagInfo
- (2)TaskInfo
- (3)TaskTagRule
- 2 工具类
- (1)连接sql的工具类
- 测试
- (2)专门读取properties文件的工具类
- 测试
- (3)对象值拷贝的工具类
- 3 配置文件
- (1)config.properties
- 4 DAO层
- (1)TagInfoDAO
- (2)TaskInfoDAO
- (3)TaskTagRuleDAO
- (4)测试
一 代码实现
第一步获得标签定义、标签任务的SQL、字标签的匹配规则,存储在MySQL中,代码实现。
task-sql任务:生成标签数据,格式为userid – tag_value,如张三的id,男。每一种三级标签会把生成的数据放到一张表中。
实现步骤:
1 获得标签定义、标签任务的SQL、子标签的匹配规则(这些数据存放在mysql中)
1.1 如何查询MySQL:封装工具类,利用jdbc
1.2 用工具类分别查询
- 一个数:String,Int,Long
- tag_info:一行数 hashmap javabean(UserInfo…)
- task_info:一行数 hashmap javabean(UserInfo…)
- task_tag_rule:一堆数,可能有很多子标签的匹配 List[UserInfo] …
1.3 如何知道要执行的哪个任务:通过spark-submit将外部参数传给spark作业,使用args获得要执行的task_id和task_date
如何将两个参数传入到args
spark-submit -driver-memory 1g --xx --xx --xx xxxx.jar taskId taskDate
xxxx.jar 后面的值会传入到args中
2 如果没有表,需要根据标签定义规则建立标签表
3 根据标签定义和规则查询数据仓库
4 把数据写入到对应的标签表中
0 开发主线
代码存放位置:task – sql – src –main – scala – com.hzy.userprofile.app – TaskSQLApp
package com.hzy.userprofile.appimport com.hzy.userprofile.bean.{TagInfo, TaskInfo, TaskTagRule}
import com.hzy.userprofile.dao.{TagInfoDAO, TaskInfoDAO, TaskTagRuleDAO}
import com.hzy.userprofile.util.MySqlUtilobject TaskSQLApp {def main(args: Array[String]): Unit = {//1 获得标签定义、标签任务的SQL、字标签的匹配规则,存储在MySQL中// 封装工具类,查询MySQL,jdbc// 用工具类分别查询tag_info、task_info、task_tag_rule// 一个数 string int long 一行数 hashmap javabean(UserInfo...) 一堆数List[UserInfo] ...// 可以通过args获得要执行的task_id和task_dateval taskId: String = args(0)val tastDate: String = args(1)//根据taskId查询tag_info、task_info、task_tag_rule//要定义javabean,转向task-common工程新建TagInfo,TaskInfo,TaskTagRule,对应标题1中的(1)(2)(3)//var tagInfo:TagInfo = null//val taskInfo:TaskInfo = null//val taskTagRuleList:List[TaskTagRule] = null//想查询出以上三条数据,需要定义连接MySQL的工具类,转向task-common工程,对应标题2中的(1)(2)(3)和3中的(1)
// val maybeTagInfo: Option[TagInfo] = MySqlUtil.queryOne(// 查询一个TagInfo,有TaskId,需要查询tag_info中的tag_task_id列
// s"""
// | select id,tag_code,tag_name,
// | parent_tag_id,tag_type,tag_value_type,
// | tag_value_limit,tag_task_id,tag_comment,
// | create_time
// | from tag_info
// | where tag_task_id='$taskId'
// |""".stripMargin,
// classOf[TagInfo],true)
//
// if(maybeTagInfo != None){// tagInfo = maybeInfo.get
// }// 将以上查询sql抽取为一个方法,放在task-common中的dao层中,对应标题4中的(1)(2)(3)// 可以通过一条语句实现查询val tagInfo: TagInfo = TagInfoDAO.getTagInfoByTaskId(taskId)val taskInfo: TaskInfo = TaskInfoDAO.getTaskInfo(taskId)val taskTagRuleList: List[TaskTagRule] = TaskTagRuleDAO.getTaskTagRuleListByTaskId(taskId)println(tagInfo)println(taskInfo)println(taskTagRuleList)//2 如果没有表,需要根据标签定义规则建立标签表//3 根据标签定义和规则查询数据仓库//4 把数据写入到对应的标签表中}
}
1 实体类
(1)TagInfo
在task-common中增加实体类TagInfo,是一个样例类,样例类本身不含有无参构造函数,但是后续过程中,需要其无参构造函数,所以需要自己定义一个无参构造函数,将有参的参数都置为null则相当于无参,def this() ={ this(null,null,null,null,null,null,null,null,null,null,null,null,null ) }
定义了一个java的long,import java.lang.Long
,因为scala中的long不接受null值
package com.hzy.userprofile.beanimport java.util.Date
import java.lang.Longcase class TagInfo(var id:Long,var tagCode:String,var tagName:String,var tagLevel:Long,var parentTagId:Long,var tagType:String,var tagValueType:String,var tagValueLimit:Long,var tagValueStep:Long,var tagTaskId:Long,var tagComment:String,var createTime:Date,var updateTime:Date) {def this() ={this(null,null,null,null,null,null,null,null,null,null,null,null,null )}
}
(2)TaskInfo
package com.hzy.userprofile.beanimport java.util.Date
import java.lang.Longcase class TaskInfo (var id: Long = null ,var taskName:String=null,var taskStatus:String=null,var taskComment:String=null,var taskTime:String=null,var taskType:String=null,var execType:String=null,var mainClass:String=null,var fileId:Long= null,var taskArgs:String=null,var taskSql:String=null,var taskExecLevel:Long =null,var createTime:Date=null) {//补充无参构造函数def this() ={this(0L,null,null,null,null,null,null,null,-1L,null,null,null,null)}
}
(3)TaskTagRule
package com.hzy.userprofile.beanimport java.lang.Longcase class TaskTagRule(var id:Long,var tagId:Long,var taskId:Long,var queryValue:String,var subTagId:Long,var subTagValue:String) {def this() ={this(null,null,null,null,null,null )}
}
2 工具类
(1)连接sql的工具类
MySqlUtil工具类中包含三个方法:
ueryList(sql: String): java.util.List[JSONObject]
:返回List[JSONObject],JSON本质上也是一个HashMap,是一个KV对象,只不过能够更加容易的转换为JSON,通用结构queryList[T<:AnyRef](sql: String, clazz: Class[T], underScoreToCamel: Boolean):List[T]
:将数据转换成专用结构,需要传入的参数:- 一个sql、一个类clazz:意思为将这个sql封装成clazz的类型
- underScoreToCamel:作用为将sql字段转换为java的驼峰结构AaBb
queryOne[T<:AnyRef](sql: String, clazz: Class[T] ,underScoreToCamel: Boolean): Option[T ]
:查询单条数据,实现方式也是查询集合,只不过如果集合不为空,将集合中的第一条数据抓取出来
package com.hzy.userprofile.utilimport java.lang.reflect.Field
import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet, ResultSetMetaData, Statement}
import java.util.Properties
import com.alibaba.fastjson.JSONObject
import com.google.common.base.CaseFormat
import scala.collection.mutable.ListBufferobject MySqlUtil {def main(args: Array[String]): Unit = {val list: java.util.List[JSONObject] = queryList("select * from base_province")println(list)}private val properties: Properties = MyPropertiesUtil.load("config.properties")val MYSQL_URL = properties.getProperty("mysql.url")val MYSQL_USERNAME = properties.getProperty("mysql.username")val MYSQL_PASSWORD = properties.getProperty("mysql.password")def queryList(sql: String): java.util.List[JSONObject] = {Class.forName("com.mysql.jdbc.Driver")//创建结果列表val resultList: java.util.List[JSONObject] = new java.util.ArrayList[JSONObject]()//创建连接val conn: Connection = DriverManager.getConnection(MYSQL_URL, MYSQL_USERNAME, MYSQL_PASSWORD)//创建会话val stat: Statement = conn.createStatementprintln(sql)//提交sql 返回结果val rs: ResultSet = stat.executeQuery(sql)//为了获得列名 要取得元数据val md: ResultSetMetaData = rs.getMetaDatawhile (rs.next) {val rowData = new JSONObject();for (i <- 1 to md.getColumnCount) {// 根据下标得到对应元数据中的字段名,以及结果中值rowData.put(md.getColumnName(i), rs.getObject(i))}resultList.add(rowData)}stat.close()conn.close()resultList}def queryList[T<:AnyRef](sql: String, clazz: Class[T], underScoreToCamel: Boolean):List[T]={Class.forName("com.mysql.jdbc.Driver");val resultList: ListBuffer[T] = new ListBuffer[T]();val connection: Connection = DriverManager.getConnection(MYSQL_URL, MYSQL_USERNAME, MYSQL_PASSWORD)val stat: Statement = connection.createStatement();val rs: ResultSet = stat.executeQuery(sql);val md: ResultSetMetaData = rs.getMetaData();while (rs.next()) {val obj: T = clazz.newInstance()for (i <- 1 to md.getColumnCount) {var propertyName: String = md.getColumnLabel(i)if (underScoreToCamel) {propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, md.getColumnLabel(i))}MyBeanUtils.setV(obj,propertyName,rs.getObject(i))}resultList.append(obj);}stat.close()connection.close()resultList.toList}def queryOne[T<:AnyRef](sql: String, clazz: Class[T] ,underScoreToCamel: Boolean): Option[T ] ={println(sql)Class.forName("com.mysql.jdbc.Driver");val resultList: ListBuffer[T] = new ListBuffer[T]();val connection: Connection =DriverManager.getConnection(MYSQL_URL, MYSQL_USERNAME, MYSQL_PASSWORD)val stat: Statement = connection.createStatement();val rs: ResultSet = stat.executeQuery(sql);val md: ResultSetMetaData = rs.getMetaData();while (rs.next()) {val obj: T = clazz.newInstance()for (i <- 1 to md.getColumnCount) {var propertyName: String = md.getColumnName(i)if (underScoreToCamel) {propertyName =CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, md.getColumnName(i))}MyBeanUtils.setV(obj,propertyName,rs.getObject(i))}resultList.append(obj);}stat.close()connection.close()if(resultList!=null){Some(resultList(0))}else{None}}def insertOne[T](sql: String, obj:T ): Unit ={Class.forName("com.mysql.jdbc.Driver");val resultList: ListBuffer[T] = new ListBuffer[T]();val connection: Connection =DriverManager.getConnection(MYSQL_URL, MYSQL_USERNAME, MYSQL_PASSWORD)val pstat: PreparedStatement = connection.prepareStatement(sql)val fields: Array[Field] = obj.getClass.getDeclaredFieldsfor(i<- 1 to fields.size){val field:Field = fields(i-1);field.setAccessible(true)val value: AnyRef = field.get(obj)pstat.setObject(i,value)}val resInsert = pstat.execute()println("插入数据,返回值=>" + resInsert)}
}
测试
def main(args: Array[String]): Unit = {val list: java.util.List[JSONObject] = queryList("select * from tag_info")println(list)
}
运行上述代码进行测试,会发现抛出错误信息如下
Exception in thread “main” java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
查看maven工程中的依赖,发现驱动存在,进而查看父工程的配置文件pom.xml,发现mysql驱动的依赖为
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version><scope>provided</scope></dependency>
<scope>
影响依赖在何时加入,provided为在编写代码时将依赖引入进去,编译可以通过,但是运行、打包时就不会加入此条依赖。
加入provided原因:task-sql程序最终会打成jar包,如果不写provided,所有的依赖都会打一个jar包,最终的jar包会变得十分臃肿,称为”胖包“,有一部分类不用放到jar包中,可以放到运行环境中,spark-lib下存在mysql驱动包,所以此处为provided。
现想要在idea中调试运行,解决办法如下图:
(2)专门读取properties文件的工具类
Properties底层实现就是一个hashmap,配置文件中“等于号”前的为K值,后面的为V值
package com.hzy.userprofile.utilimport java.io.InputStreamReader
import java.util.Propertiesobject MyPropertiesUtil {def main(args: Array[String]): Unit = {val properties: Properties = MyPropertiesUtil.load("config.properties")println(properties.getProperty("kafka.broker.list"))}def load(propertieName:String): Properties ={val prop=new Properties();prop.load(new InputStreamReader(Thread.currentThread().getContextClassLoader.getResourceAsStream(propertieName) , "UTF-8"))prop}
}
测试
替换上述代码中main方法中的参数
def main(args: Array[String]): Unit = {val properties: Properties = MyPropertiesUtil.load("config.properties")println(properties.getProperty("mysql.url"))}
修改上述代码,可测试代码是否正确
(3)对象值拷贝的工具类
MyBeanUtils.setV(obj,propertyName,rs.getObject(i))
希望将rs.getObject(i)获得的值拷贝到obj对象的propertyName属性中。
平常用对象赋值都是写一个固定的setA(A)
,如果对象中有很多值,想循环的赋值,上面写法就不行,因为A不确定,所以可以将A作为一个变量,循环执行。
package com.hzy.userprofile.utilimport java.lang.reflect.{Field, Modifier}
import java.text.SimpleDateFormat
import java.util.Locale
import scala.util.control.Breaks._object MyBeanUtils {/*** 对象相同属性copy** @param obj* @param toResult* @return* @throws Exception* 转换报错*/def copyProperties(obj: Object, toResult: Object): Unit = {if (obj == null) {return}try {val fields = toResult.getClass.getDeclaredFieldsfor (field <- fields) {breakable {field.setAccessible(true) //修改访问权限if (Modifier.isFinal(field.getModifiers()))breakif (isWrapType(field)) {val getMethodName = field.getName()val setMethodName = field.getName()+"_$eq"val getMethod = {try {obj.getClass().getMethod(getMethodName)} catch {case ex: Exception =>// println(ex)break}}//从源对象获取get方法val setMethod =toResult.getClass.getMethod(setMethodName, field.getType)//从目标对象获取set方法val value = {val objValue = getMethod.invoke(obj) // get 获取的是源对象的值if (objValue != null && objValue.isInstanceOf[java.util.Date]) {// GMT时间转时间戳val format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)val formatValue = format.format(objValue)java.lang.Long.valueOf(format.parse(formatValue).getTime)} elseobjValue}setMethod.invoke(toResult, value)}}}} catch {case ex: Exception => throw ex}}/*** 是否是基本类型、包装类型、String类型*/def isWrapType(field: Field): Boolean = {val typeList = List[String]("java.lang.Integer", "java.lang.Double", "java.lang.Float", "java.lang.Long", "java.util.Optional", "java.lang.Short", "java.lang.Byte", "java.lang.Boolean", "java.lang.Char", "java.lang.String", "int", "double", "long", "short", "byte", "boolean", "char", "float")if (typeList.contains(field.getType().getName())) true else false}def getV(ref:AnyRef, name: String): Any = ref.getClass.getMethods.find(_.getName == name).get.invoke(ref)def setV(ref:AnyRef,name: String, value: Any): Unit = {ref.getClass.getMethods.find(_.getName == name + "_$eq").get.invoke(ref, value.asInstanceOf[AnyRef])}
}
核心为下述代码
def setV(ref:AnyRef,name: String, value: Any): Unit = {ref.getClass.getMethods.find(_.getName == name + "_$eq").get.invoke(ref, value.asInstanceOf[AnyRef])
使用java的反射机制,找到对象,只不过对象与java中不同,scala给属性赋值的方法叫做name + "_$eq"
,其中的$就是=,scala反编译重新做了一个编码。
找到name + "_$eq"
方法,进行反射,进而赋值。
3 配置文件
task-common – resources 增加配置文件
(1)config.properties
hdfs-store.path=hdfs://bigdata01:8020/user_profile
data-warehouse.dbname=gmall2021
user-profile.dbname=user_profile2077#mysql配置
mysql.url=jdbc:mysql://127.0.0.1:3306/user_profile_manager_1009?characterEncoding=utf-8&useSSL=false
mysql.username=root
mysql.password=hike
4 DAO层
(1)TagInfoDAO
package com.hzy.userprofile.daoimport com.hzy.userprofile.bean.TagInfo
import com.hzy.userprofile.util.MySqlUtilobject TagInfoDAO {def getTagInfoByTaskId(taskId:String): TagInfo ={val tagInfoSql: String =s"""select id,tag_code,tag_name,| parent_tag_id,tag_type,tag_value_type,| tag_value_limit,tag_task_id,tag_comment,| create_time| from tag_info| where tag_task_id=$taskId""".stripMarginval tagInfoOpt: Option[TagInfo] =MySqlUtil.queryOne(tagInfoSql, classOf[TagInfo], true)var tagInfo: TagInfo = null;if (tagInfoOpt != None) {tagInfo = tagInfoOpt.get} else {throw new RuntimeException("no tag for task_id : "+taskId)}tagInfo}
}
(2)TaskInfoDAO
package com.hzy.userprofile.daoimport com.hzy.userprofile.bean.TaskInfo
import com.hzy.userprofile.util.MySqlUtilobject TaskInfoDAO {def getTaskInfo( taskId:String): TaskInfo ={val taskInfoSql: String =s"""select id,task_name,| task_status,task_comment,task_time ,| task_type,exec_type,main_class,file_id,| task_args,task_sql,task_exec_level,create_time| from task_info where id=$taskId""".stripMarginval taskInfoOpt: Option[TaskInfo] =MySqlUtil.queryOne(taskInfoSql, classOf[TaskInfo], true)var taskInfo: TaskInfo = null;if (taskInfoOpt != None) {taskInfo = taskInfoOpt.get} else {throw new RuntimeException("no task for task_id : "+taskId)}taskInfo}
}
(3)TaskTagRuleDAO
package com.hzy.userprofile.daoimport com.hzy.userprofile.bean.TaskTagRule
import com.hzy.userprofile.util.MySqlUtilobject TaskTagRuleDAO {def getTaskTagRuleListByTaskId(taskId:String): List[TaskTagRule] ={// 需两表的关联// task_tag_rule中的query_value为FMU,对应的sub_tag_id为8,9,10// 8,9,10没用,想要男,女,未知,所以需要将8,9,10换成标签的值// 作法:用8,9,10关联tag_info中的idval taskRuleSql: String =s"""select tr.id,tr.tag_id,tr.task_id,tr.query_value,| sub_tag_id,ti.tag_name as sub_tag_value| from task_tag_rule tr,tag_info ti| where tr.sub_tag_id=ti.id and tr.task_id=$taskId""".stripMarginval taskTagRuleList: List[TaskTagRule] =MySqlUtil.queryList(taskRuleSql, classOf[TaskTagRule], true)taskTagRuleList}
}
(4)测试
在user-profile-task1009\task-sql\src\main\scala\com\hzy\userprofile\app\TaskSQLApp.scala完成DAO层的测试
传递args(0),args(1)的值,传递过程如下图:
添加三条语句,完成测试
println(tagInfo)
println(taskInfo)
println(taskTagRuleList)
运行结果
select id,tag_code,tag_name,parent_tag_id,tag_type,tag_value_type,tag_value_limit,tag_task_id,tag_comment,create_timefrom tag_infowhere tag_task_id=1
log4j:WARN No appenders could be found for logger (ru.yandex.clickhouse.ClickHouseDriver).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
select id,task_name,task_status,task_comment,task_time ,task_type,exec_type,main_class,file_id,task_args,task_sql,task_exec_level,create_timefrom task_info where id=1
//TagInfo
TagInfo(7,TG_BASE_PERSONA_GENDER,性别,null,5,1,3,null,null,1,null,2022-10-09 16:20:11.0,null)
//TaskInfo
TaskInfo(1,标签计算:性别,1,计算用户性别,02:40,TAG,SQL,null,null,--driver-memory=1G
--num-executor=3
--executor-memory=2G
--executor-cores=2
--conf spark.default.parallelism=12,select id as uid,if(gender is null, 'U',gender) as query_value from dim_user_info where dt='9999-99-99',100,null)
//TaskTagRule
List(TaskTagRule(1,7,1,F,8,男), TaskTagRule(2,7,1,M,9,女), TaskTagRule(3,7,1,U,10,未知))
至此,开发主线中的第一步【获得标签定义、标签任务的SQL、字标签的匹配规则】已经完成。
【用户画像】标签任务开发流程(源码之实体类、工具类、配置文件、DAO层)相关推荐
- 用户画像标签数据开发之标签相似度计算
目录 0. 相关文章链接 1. 什么是标签相似度计算 2. 案例场景 3. 数据开发 注:此博文为根据 赵宏田 老师的 用户画像·方法论与工程化解决方案 一书读后笔记而来,仅供学习使用 0. 相关文章 ...
- 用户画像标签数据开发之用户特征库开发
目录 0. 相关文章链接 1. 什么是用户特征库 2. 特征库规划 3. 数据开发 4. 其他特征库规划 注:此博文为根据 赵宏田 老师的 用户画像·方法论与工程化解决方案 一书读后笔记而来,仅供学习 ...
- 用户画像标签数据开发之组合标签计算
目录 0. 相关文章链接 1. 什么是组合标签计算 2. 应用场景 3. 数据计算 注:此博文为根据 赵宏田 老师的 用户画像·方法论与工程化解决方案 一书读后笔记而来,仅供学习使用 0. 相关文章链 ...
- python用户画像_新闻个性化推荐系统源码之构建离线用户和文章特征
我们完成了文章画像和用户画像的构建,画像数据主要是提供给召回阶段的各种召回算法使用.接下来,我们还要为排序阶段的各种排序模型做数据准备,通过特征工程将画像数据进一步加工为特征数据,以供排序模型直接使用 ...
- OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例
2019独角兽企业重金招聘Python工程师标准>>> 本文主要讲解OpenJDK观察者模式的2个工具类,java.util.Observer观察者接口,java.util.Obse ...
- java 集合反射_关于granite源码包CollectionUtil集合工具类获取集合反射类型、实例化各种集合类型HashSet/ArrayList等...
一.前言 基于granite源码包org.granite.util.CollectionUtil集合工具类,分别获取集合反射类型java.lang.reflect.Type.实例化newCollect ...
- java.util.list源码_关于fest-util源码包Collections集合工具类过滤、判空、格式化及复制克隆处理...
一.前言 关于fest-util源码包org.fest.util.Collections集合处理类,实现对数组转换List序列集合.集合duplicatesFrom克隆复制.集合判空isEmpty.并 ...
- Go语言使用之JSO使用、源码解析和JSON工具类
在go语言网络编程中,经常会有这样的需求:保存结构体和读取结构体数据.如果你使用redis数据库存储数据,你怎么做?Redis仅支持五种数据类型( String(字符串) .Hash (哈希).Lis ...
- 全网超详细!用户画像标签体系建设指南!
大家好,最近工作之余看了很多用户画像的文章,要么描述浅显.要么相对片面,对于数据分析人员来说算是窥中豹管. 今天我将结合日常工作实践和理解,整理了一份用户画像的文章,内容偏向数据分析方法论,个人觉得这 ...
- 万字用户画像标签体系建设分析指南!
转自:大数据梦想家 01 什么是用户画像 用户画像是指根据用户的属性.用户偏好.生活习惯.用户行为等信息而抽象出来的标签化用户模型.通俗说就是给用户打标签,而标签是通过对用户信息分析而来的高度精炼的特 ...
最新文章
- CentOS 安装Zabbix 手记
- 我的博客今天6岁298天了,我领取了元老博主徽章
- 计算机网络的网络层功能在内完成,计算机网络习题及答案
- linux服务器情况
- perl6 HTTP::UserAgent (2)
- clientX和clientY属性需要注意的地方
- Rivian计划在乔治亚州新增一个工厂
- BZOJ 4310 二分+SA+RMQ
- 工作分析文献综述_学术知识| 如何撰写文献综述
- python中字典的几个方法介绍
- 微信小程序实现底部导航栏自定义tabBar
- 矩阵迹的几何意义是什么?
- [zz] 导致你创业失败的18个错误 [2007-05-03]
- 优动漫PAINT是什么?有哪些功能和特色
- 【浏览器】解决火狐和Chrome上不了网,只有IE能上网的问题
- 国家著作权: DNA 计算公式, 肽展定理公式与 变嘧啶 推导.
- 写一个辨别素数的函数,在主函数输入一个整数,输出是否为素数信息。
- java 私有类_Java类属性的私有化
- 九宫格游戏c语言代码,C++代码实现寻找九宫格游戏所有答案
- Stata:系数为何不显著?GIF 演示 OLS 的性质
热门文章
- iOS开发——frame和bounds详解
- 工业物联网有什么特征
- 雷电2接口_代替你电脑的所有接口,世界最快的雷电3了解一下
- 工具类(Excel)[一]
- 达内php难吗,深圳达内php教学好吗 说说我学习的经历
- 大S产女获张兰连续两天探望 大赞儿媳妇是骄傲
- 苹果7 无线流量连接不上网络连接服务器,iPhone7连不上wifi无线网的四种解决方法...
- 45个android实例源码
- 2020计算机夏令营+预推免统计
- Linux服务器带宽占用高导致无法登录的处理经验分享