详解Java实现的k-means聚类算法
需求
对MySQL数据库中某个表的某个字段执行k-means算法,将处理后的数据写入新表中。
源码及驱动
kmeans_jb51.rar
源码
importjava.sql.*;
importjava.util.*;
/**
*@authortianshl
*@version2018/1/13上午11:13
*/
publicclassKmeans{
//源数据
privateListorigins=newArrayList<>();
//分组数据
privateMap>grouped;
//初始质心列表
privateListcores;
//数据源
privateStringtableName;
privateStringcolName;
/**
*构造方法
*
*@paramtableName源数据表名称
*@paramcolName源数据列名称
*@paramcores质心列表
*/
privateKmeans(StringtableName,StringcolName,Listcores){
this.cores=cores;
this.tableName=tableName;
this.colName=colName;
}
/**
*重新计算质心
*
*@return新的质心列表
*/
privateListnewCores(){
ListnewCores=newArrayList<>();
for(Listv:grouped.values()){
newCores.add(v.stream().reduce(0,(sum,num)->sum+num)/(v.size()+0.0));
}
Collections.sort(newCores);
returnnewCores;
}
/**
*判断是否结束
*
*@returnbool
*/
privateBooleanisOver(){
List_cores=newCores();
for(inti=0,len=cores.size();i();
Doublecore;
for(Integerorigin:origins){
core=getCore(origin);
if(!grouped.containsKey(core)){
grouped.put(core,newArrayList<>());
}
grouped.get(core).add(origin);
}
}
/**
*选择质心
*
*@paramnum要分组的数据
*@return质心
*/
privateDoublegetCore(Integernum){
//差列表
Listdiffs=newArrayList<>();
//计算差
for(Doublecore:cores){
diffs.add(Math.abs(num-core));
}
//最小差->索引->对应的质心
returncores.get(diffs.indexOf(Collections.min(diffs)));
}
/**
*建立数据库连接
*@returnconnection
*/
privateConnectiongetConn(){
try{
//URL指向要访问的数据库名mydata
Stringurl="jdbc:mysql://localhost:3306/data_analysis_dev";
//MySQL配置时的用户名
Stringuser="root";
//MySQL配置时的密码
Stringpassword="root";
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//声明Connection对象
Connectionconn=DriverManager.getConnection(url,user,password);
if(conn.isClosed()){
System.out.println("连接数据库失败!");
returnnull;
}
System.out.println("连接数据库成功!");
returnconn;
}catch(Exceptione){
System.out.println("连接数据库失败!");
e.printStackTrace();
}
returnnull;
}
/**
*关闭数据库连接
*
*@paramconn连接
*/
privatevoidclose(Connectionconn){
try{
if(conn!=null&&!conn.isClosed())conn.close();
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*获取源数据
*/
privatevoidgetOrigins(){
Connectionconn=null;
try{
conn=getConn();
if(conn==null)return;
Statementstatement=conn.createStatement();
ResultSetrs=statement.executeQuery(String.format("select%sfrom%s",colName,tableName));
while(rs.next()){
origins.add(rs.getInt(1));
}
conn.close();
}catch(Exceptione){
e.printStackTrace();
}finally{
close(conn);
}
}
/**
*向新表中写数据
*/
privatevoidwrite(){
Connectionconn=null;
try{
conn=getConn();
if(conn==null)return;
//创建表
Statementstatement=conn.createStatement();
//删除旧数据表
statement.execute("DROPTABLEIFEXISTSk_means;");
//创建新表
statement.execute("CREATETABLEIFNOTEXISTSk_means(`core`DECIMAL(11,7),`col`INTEGER(11));");
//禁止自动提交
conn.setAutoCommit(false);
PreparedStatementps=conn.prepareStatement("INSERTINTOk_meansVALUES(?,?)");
for(Map.Entry>entry:grouped.entrySet()){
Doublecore=entry.getKey();
for(Integervalue:entry.getValue()){
ps.setDouble(1,core);
ps.setInt(2,value);
ps.addBatch();
}
}
//批量执行
ps.executeBatch();
//提交事务
conn.commit();
//关闭连接
conn.close();
}catch(Exceptione){
e.printStackTrace();
}finally{
close(conn);
}
}
/**
*处理数据
*/
privatevoidrun(){
System.out.println("获取源数据");
//获取源数据
getOrigins();
//停止分组
BooleanisOver=false;
System.out.println("数据分组处理");
while(!isOver){
//数据分组
setGrouped();
//判断是否停止分组
isOver=isOver();
}
System.out.println("将处理好的数据写入数据库");
//将分组数据写入新表
write();
System.out.println("写数据完毕");
}
publicstaticvoidmain(String[]args){
Listcores=newArrayList<>();
cores.add(260.0);
cores.add(600.0);
//表名,列名,质心列表
newKmeans("attributes","attr_length",cores).run();
}
}
源文件
Kmeans.java
编译
javacKmeans.java
运行
#指定依赖库 java-Djava.ext.dirs=./libKmeans
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。