需求
對MySQL數據庫中某個表的某個字段執行k-means算法,將處理后的數據寫入新表中。
源碼及驅動
源碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
import java.sql.*; import java.util.*; /** * @author tianshl * @version 2018/1/13 上午11:13 */ public class Kmeans { // 源數據 private List<Integer> origins = new ArrayList<>(); // 分組數據 private Map<Double, List<Integer>> grouped; // 初始質心列表 private List<Double> cores; // 數據源 private String tableName; private String colName; /** * 構造方法 * * @param tableName 源數據表名稱 * @param colName 源數據列名稱 * @param cores 質心列表 */ private Kmeans(String tableName, String colName,List<Double> cores){ this .cores = cores; this .tableName = tableName; this .colName = colName; } /** * 重新計算質心 * * @return 新的質心列表 */ private List<Double> newCores(){ List<Double> newCores = new ArrayList<>(); for (List<Integer> v: grouped.values()){ newCores.add(v.stream().reduce( 0 , (sum, num) -> sum + num) / (v.size() + 0.0 )); } Collections.sort(newCores); return newCores; } /** * 判斷是否結束 * * @return bool */ private Boolean isOver(){ List<Double> _cores = newCores(); for ( int i= 0 , len=cores.size(); i<len; i++){ if (!cores.get(i).toString().equals(_cores.get(i).toString())){ // 使用新質心 cores = _cores; return false ; } } return true ; } /** * 數據分組 */ private void setGrouped(){ grouped = new HashMap<>(); Double core; for (Integer origin: origins) { core = getCore(origin); if (!grouped.containsKey(core)) { grouped.put(core, new ArrayList<>()); } grouped.get(core).add(origin); } } /** * 選擇質心 * * @param num 要分組的數據 * @return 質心 */ private Double getCore(Integer num){ // 差 列表 List<Double> diffs = new ArrayList<>(); // 計算差 for (Double core: cores){ diffs.add(Math.abs(num - core)); } // 最小差 -> 索引 -> 對應的質心 return cores.get(diffs.indexOf(Collections.min(diffs))); } /** * 建立數據庫連接 * @return connection */ private Connection getConn(){ try { // URL指向要訪問的數據庫名mydata String url = "jdbc:mysql://localhost:3306/data_analysis_dev" ; // MySQL配置時的用戶名 String user = "root" ; // MySQL配置時的密碼 String password = "root" ; // 加載驅動 Class.forName( "com.mysql.jdbc.Driver" ); //聲明Connection對象 Connection conn = DriverManager.getConnection(url, user, password); if (conn.isClosed()){ System.out.println( "連接數據庫失敗!" ); return null ; } System.out.println( "連接數據庫成功!" ); return conn; } catch (Exception e) { System.out.println( "連接數據庫失敗!" ); e.printStackTrace(); } return null ; } /** * 關閉數據庫連接 * * @param conn 連接 */ private void close(Connection conn){ try { if (conn != null && !conn.isClosed()) conn.close(); } catch (Exception e){ e.printStackTrace(); } } /** * 獲取源數據 */ private void getOrigins(){ Connection conn = null ; try { conn = getConn(); if (conn == null ) return ; Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery(String.format( "select %s from %s" , colName, tableName)); while (rs.next()){ origins.add(rs.getInt( 1 )); } conn.close(); } catch (Exception e){ e.printStackTrace(); } finally { close(conn); } } /** * 向新表中寫數據 */ private void write(){ Connection conn = null ; try { conn = getConn(); if (conn == null ) return ; // 創建表 Statement statement = conn.createStatement(); // 刪除舊數據表 statement.execute( "DROP TABLE IF EXISTS k_means; " ); // 創建新表 statement.execute( "CREATE TABLE IF NOT EXISTS k_means(`core` DECIMAL(11, 7), `col` INTEGER(11));" ); // 禁止自動提交 conn.setAutoCommit( false ); PreparedStatement ps = conn.prepareStatement( "INSERT INTO k_means VALUES (?, ?)" ); for (Map.Entry<Double, List<Integer>> entry: grouped.entrySet()){ Double core = entry.getKey(); for (Integer value: entry.getValue()){ ps.setDouble( 1 , core); ps.setInt( 2 , value); ps.addBatch(); } } // 批量執行 ps.executeBatch(); // 提交事務 conn.commit(); // 關閉連接 conn.close(); } catch (Exception e){ e.printStackTrace(); } finally { close(conn); } } /** * 處理數據 */ private void run(){ System.out.println( "獲取源數據" ); // 獲取源數據 getOrigins(); // 停止分組 Boolean isOver = false ; System.out.println( "數據分組處理" ); while (!isOver) { // 數據分組 setGrouped(); // 判斷是否停止分組 isOver = isOver(); } System.out.println( "將處理好的數據寫入數據庫" ); // 將分組數據寫入新表 write(); System.out.println( "寫數據完畢" ); } public static void main(String[] args){ List<Double> cores = new ArrayList<>(); cores.add( 260.0 ); cores.add( 600.0 ); // 表名, 列名, 質心列表 new Kmeans( "attributes" , "attr_length" , cores).run(); } } |
源文件
1
|
Kmeans.java |
編譯
1
|
javac Kmeans.java |
運行
1
2
|
# 指定依賴庫 java -Djava.ext.dirs=./lib Kmeans |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://my.oschina.net/tianshl/blog/1606526