目录
实验一:
实现一个名为Value 的类,其中含有一个字符类型的成员x 和双精度类型的成员y。请重写(override)其equals( )方法,使得用equals( )比较Value 类的两个对象的内容时,相等条件是对象的所有成员分别对应相等。
在Object类中,equals方法默认使用“==”号来对两个对象进行判断,比较的是两个对象的地址值,这就意味着当两个对象不是同一个时(地址值不一致就不是同一个对象),就返回为false。因此对于两个储存地址不一样但内容相同的对象需要重写equals方法。本题要求比较的Value类中的两个成员,double类型的x,直接使用“==”对其的值是否相等进行判断,String类型的y,由于String类型的equals已经进行了重写,可以直接调用y.equals(obj.y)进行判断。若都不符合或类型不是Value类及其子类,则返回false
- 实验源码
import java.util.*; public class Chongxie { public static void main(String[] args) { Value a = new Value(1,"hahaha"); Value b = new Value(1,"hahaha"); Value c = new Value(2,"hahaha"); Value d = new Value(1,"1hahaha"); Value e = new Value(2,"1hahaha"); if(e.equals(d)) { System.out.println("相等"); } else System.out.println("不相等"); } } class Value{ String y; double x; public double getx() { return this.x; } public String gety() { return y; } Value(double a,String b){ y = b; x = a; } @Override public boolean equals(Object obj) { if(obj instanceof Value) { Value tmp = (Value)obj; if(tmp.getx()!=this.x) return false; return y.equals(tmp.gety()); } return false; } }
此题涉及到equals的重写,在完成此实验的过程中复习了重写和equals的知识点。在重写equals方法时,要注意满足以下事项:
- 自反性:对于任意的引用值x,x.equals(x)一定为true。
- 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true时, y.equals(x)也一定返回true。
- 传递性:对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。
- 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改,多次调用x.equals(y)要么一致地返回true,要么一致地返回false。
- 非空性:对于任意的非空引用值x,x.equals(null)一定返回false。
在完成重写后,分别测试了以下情况,结果均正确。
X | Y |
相同 | 相同 |
相同 | 不相同 |
不相同 | 相同 |
不相同 | 不相同 |
实验二:
使用Lambda表达式比较器Comparator给List对象排序,分别按Name、Age(倒序)、Grade排序。List对象内容如下表:
ID | Name | Age | Grade |
1 | ZhangSan | 28 | 98 |
2 | LiSi | 21 | 100 |
3 | KangKang | 27 | 89 |
4 | LiMing | 19 | 92 |
5 | WangGang | 22 | 66 |
6 | ZhaoXin | 24 | 85 |
7 | LiuWei | 20 | 78 |
8 | BaiZhanTang | 16 | 99 |
首先创建用于排序的列表List<student> stu = new ArrayList<student>();然后向其添加元素。由于排序需要展示结果,重写tosting方法来完成输出。排序前结果如下:
按姓名排序stu.sort((student s1,student s2)->s1.name.compareTo(s2.name));,排序结果:
按年龄倒序排序stu.sort((student s1,student s2)->(s2.age - s1.age));,排序结果:
按成绩排序stu.sort((student s1,student s2)->(s1.grade - s1.grade));,排序结果:
- 实验源码
import java.util.*; public class Lambdacompare { public static void main(String[] args) { List<student> stu = new ArrayList<student>(); stu.add(new student(1,"ZhangSan",28,98)); stu.add(new student(2,"LiSi",21,100)); stu.add(new student(3,"KangKang",27,89)); stu.add(new student(4,"LiMing",19,92)); stu.add(new student(5,"WangGang",22,66)); stu.add(new student(6,"ZhaoXin",24,85)); stu.add(new student(7,"LiuWei",20,78)); stu.add(new student(8,"BaiZhanTang",16,99)); System.out.println("Before Sort:"); for(student tmpstu:stu) { System.out.println(tmpstu); } stu.sort((student s1,student s2)->s1.name.compareTo(s2.name)); System.out.println("Sort By Name:"); stu.forEach((tmpstu)->System.out.println(tmpstu)); stu.sort((student s1,student s2)->(s2.age - s1.age)); System.out.println("Sort By Age:"); stu.forEach((tmpstu)->System.out.println(tmpstu)); stu.sort((student s1,student s2)->(s1.grade - s1.grade)); System.out.println("Sort By Grade:"); stu.forEach((tmpstu)->System.out.println(tmpstu)); } } class student{ int id; String name; int age; int grade; student(int a,String b,int c,int d){ id = a; name = b; age = c; grade = d; } @Override public String toString() { return "Student(id:"+id+",name:" + name+",age:" + age +",grade"+grade+")"; } }
通过本实验,复习了list的知识点和lambda表达式的基础用法。在刚开始进行创建列表操作时误使用了new List<>();的错误操作,经过复习ppt和代码发现List是一个接口,接口无法实例化,只能实例化具体类型,例如使用ArrayList进行初始化。
实验代码尚存在不足,为了方便操作,节约篇幅,student类里的变量均使用了friendly,没有改为private并添加get()方法来获取值,后续编写代码中将注意此问题。
实验三:
打开中的lunch.java文件,一次读取其中的一行,令每行形成一个String对象。然后利用java.util.Comparator接口重新定义String对象间的比较方法:将每个String中的小写字母转为大写后再进行比较。使用该比较法对这些String进行排序,按从大到小的顺序存入一个LinkedList。最后将LinkedList中的String按存入的相反顺序输出到另一个文件inverse.txt中。
首先创建cmp对象重新定义compare方法,创建arraylist按行存入Lunch.java,然后对其排序,最后将使用reverse将其倒序然后存入inverse.txt中。
输出txt内容:
// Can't do this! Private constructor:
//! Soup priv1 = new Soup();
return new Soup();
return ps1;
Sandwich f1 = new Sandwich();
Soup priv2 = Soup.makeSoup();
Soup.access().f();
// (1) Allow creation via static method:
// (2) Create a static object and
// (The "Singleton" pattern):
// return a reference upon request.
private Soup() {}
private static Soup ps1 = new Soup();
public static Soup access() {
public static Soup makeSoup() {
public void f() {}
void f() { new Lunch(); }
void test() {
}
}
}
// Demonstrates class access specifiers.
// From 'Thinking in Java, 2nd ed.' by Bruce Eckel
// Make a class effectively private
// Only one public class allowed per file:
// with private constructors:
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
//: c05:Lunch.java
class Sandwich { // Uses Lunch
class Soup {
public class Lunch {
}
}
} ///:~
- 实验源码
import java.io.*; import java.util.*; public class Inversetxt { public static void main(String[] args) throws FileNotFoundException { try { BufferedReader buff = new BufferedReader(new FileReader("C:\\Users\\hpcalc\\workspace\\1\\src\\yjh\\Lunch.java")); String s; ArrayList<String> list = new ArrayList<String>(); while( (s = buff.readLine())!=null )//按行读取存入字符串数组 { list.add(s); } buff.close(); Collections.sort(list,new cmp()); LinkedList<String> list2 = new LinkedList<String>(); list2.addAll(list); File file = new File("inverse.txt"); DataOutputStream ds = new DataOutputStream(new FileOutputStream(file)); Collections.reverse(list2); for(String str:list2) ds.writeBytes(str+'\n'); ds.close(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } class cmp implements Comparator<String>{ @Override public int compare(String s1,String s2) { s1=s1.toUpperCase(); s2=s2.toUpperCase(); return s2.compareTo(s1); } }
- 实验心得
通过本实验,复习了接口和比较器的知识点和文件流操作的基础用法。同时进一步了解了Java 集合框架的功能和使用方法。
实验四:
K近邻算法是分类数据最简单有效的算法,它采用基于实例的学习方法。简单地说,它采用测量不同样本之间距离的方法进行分类。它的工作原理是:存在一个样本数据集合,也称为训练样本集,并且样本集中的每个数据都有标签,即我们知道每个数据所属的分类。输入没有标签的新数据之后,将新数据的每个特征与样本集中数据的对应特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前K个最相似的数据,这就是K近邻算法中K的出处。最后,选择K个最相似数据中出现次数最多的分类。
要求设计和实现类KnnNumber,构造一个使用K近邻分类器的手写识别系统,该系统可以识别数字0到9.需要识别的数字已经处理成具有相同的色彩和大小:使用文本格式表示的32像素*32像素黑白图像(0/1二值图像)。数据集在digits.zip中。其中目录trainingDigits包含了训练样本集,其中包含了大约2000个样本数据,每个数据的文件名表明了它的标签(0~9的某个数字),每个数字大约有200个样本数据;目录testDigits中包含了大约900个测试数据。请合理设计KnnNumber的数据成员和成员方法,以实现算法的各个步骤。将K取值为[3,9]之间的一个整数,找出分类准确率最高的K值。
首先创建一个内部类digits用于储存数据集以及其总数和标签,在digits类里创建creat方法用于从文件创建数据集,将每一个32*32的二进制值储存为矩阵的行向量。
其次创建knn方法,其实现方法为将测试集的一条1*n的数据取出重复扩展到m*n的矩阵,其中m为训练集数据的行数,n为一条向量的长度。将其与训练集的矩阵作差得到每一个维度的差,再将其平方求和得到欧氏距离的平方作为其距离用于筛选距离最近的点。
最后在KnnNumber中的main方法完成创建训练集和测试集数据并创建循环调用knn方法进行运算,得到以下结果:
- 实验源码
import java.io.*; import java.util.*; public class KnnNumber { static int result=0; class digits{ int[][] data; int[] value; int n; void creat(String path) { File f = new File(path); String[] dir = f.list(); System.out.println(dir); n = dir.length; //这里出过错 this.data = new int[n][1024]; this.value = new int[n]; for(int i=0;i<n;i++) { try { BufferedReader br = new BufferedReader(new FileReader(path+"\\"+dir[i])); char[] s=new char[34]; for(int j=0;j<32;j++) { br.read(s,0,34); for(int k=0;k<32;k++) data[i][j*32+k]=(int)(s[k]-'0'); } br.close(); } catch (IOException e) { System.out.println(e.getMessage()); } String[] str=dir[i].split("_"); value[i]=Integer.parseInt(str[0]); } System.out.println("read "+path+" ok!"); } } public static void main(String[] args) { Knn t = new Knn(); digits train = t.new digits(); digits test = t.new digits(); train.creat("C:\\Users\\hpcalc\\workspace\\1\\src\\trainingDigits"); test.creat("C:\\Users\\hpcalc\\workspace\\1\\src\\testDigits"); //List //result = t.knn(test.data[0], 3, train); //System.out.println(result); int bestk=0; double tmpacc = 0; System.out.println("测试集总数:"+test.n+",测试开始"); for(int k=3;k<=9;k++) { double err=0; for(int i=0;i<test.n;i++) { result = t.knn(test.data[i], k, train); if(result!=test.value[i]) err++; System.out.println("k值:"+k+"测试数据"+(i+1)+":"+"预测值"+result+",真实值为"+test.value[i]+"预测正误:"+(result==test.value[i])); } //输出 double acc = (1-(double)err/test.n)*100; System.out.println("k值:"+k+",误判数:"+(int)err+",准确率:"+acc); if(acc>tmpacc) { tmpacc = acc; bestk = k; } } System.out.println("完成!"); System.out.println("准确率最高的k值:"+bestk+",准确率:"+tmpacc); } int knn(int[] data,int k,digits train) { int[][] dtest = new int[train.n][1024]; double[][] dist = new double[train.n][2]; //储存每个距离 for(int i=0;i<train.n;i++) for(int j=0;j<1024;j++) dtest[i][j]=data[j]; for(int i=0;i<train.n;i++) for(int j=0;j<1024;j++) dtest[i][j] = (int) Math.pow(dtest[i][j]-train.data[i][j], 2); for(int i=0;i<train.n;i++) {//计算欧氏距离的平方 dist[i][0] = i; dist[i][1] = 0; for(int j=0;j<1024;j++) dist[i][1]+=dtest[i][j]; } Arrays.sort(dist,new Comparator<double[]>(){ @Override public int compare(double[] a,double[] b) { if(a[1]>b[1]) return 1; else if(a[1]<b[1]) return -1; else return 0; } }); int[] like = new int[10]; for(int i=0;i<10;i++) { like[i] = 0; } for(int i=0;i<k;i++) { like[train.value[(int)dist[i][0]]]++; } int tmp = -999; int index = 0; for(int i=0;i<10;i++) { if(tmp<like[i]) { tmp = like[i]; index = i; } } return index; }
- 实验心得
通过本实验,学习了knn算法,复习了内部类和io的知识点,熟练了java代码的编写。在完成本实验的过程中进一步了解了各个类的length的具体含义。
实验五:
K-means算法是经典的聚类算法,其基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。假设要把样本集分为K个类别,算法描述如下:
(1)适当选择k个类的初始中心
(2)在第I次迭代中,对任意一个样本,求其到K个中心的距离,将该样本归到距离最短的中心所在的类
(3)利用均值方式更新该类的中心值
(4)对于所有的K个聚类中心,如果利用(2)(3)的迭代法更新后,值保持基本不变,则迭代结束,否则继续迭代。
要求用java编写K-means算法(k值可以自己设定),根据花的属性对数据集Iris Data Set进行聚类,并将聚类结果(sepal length,sepal width,petal length,petal width ,cluster label)打印至cluster.txt文件。
iris数据包括四个属性:sepal length花萼长度,sepal width花萼宽度,petal length花瓣长度,petal width花瓣宽度。其中第五个值表示该样本属于哪一个类。Iris.data 可以用写字板打开。
注意:样本点间的距离直接用向量的欧氏距离。
首先考虑到应对数据进行预处理,以消除量纲的影响。为了简化操作使用SPSS Statistics采用zscore方法进行数据标准化操作。完成后将数据存为iris.csv放入工作区。、
然后考虑k值的选取,因题目没有明确指定k值,考虑随意选取k值存在误差较大的情况,故采取肘方法确定k值,使用java的Graphic方法绘制sse-k值图像。
如图,肘点为k=2,应选取k=2获得较好的聚类质量。使用SPSS Modeler进行聚类分析以验证选取k值的合理性,得到聚类质量最佳的聚类数为2,符合该结果。
令k取2进行聚类得到聚类标签,将聚类结果输出到指定的文件中,文件内容如下(双击打开):
-0.89767,1.02861,-1.33679,-1.30859,0 -1.1392,-0.12454,-1.33679,-1.30859,0 -1.38073,0.33672,-1.39347,-1.30859,0 -1.50149,0.10609,-1.28012,-1.30859,0 -1.01844,1.25924,-1.33679,-1.30859,0 -0.53538,1.95113,-1.16677,-1.04652,0 -1.50149,0.79798,-1.33679,-1.17756,0 -1.01844,0.79798,-1.28012,-1.30859,0 -1.74302,-0.35517,-1.33679,-1.30859,0 -1.1392,0.10609,-1.28012,-1.43963,0 -0.53538,1.48987,-1.28012,-1.30859,0 -1.25996,0.79798,-1.22344,-1.30859,0 -1.25996,-0.12454,-1.33679,-1.43963,0 -1.86378,-0.12454,-1.50682,-1.43963,0 -0.05233,2.18176,-1.45015,-1.30859,0 -0.17309,3.10428,-1.28012,-1.04652,0 -0.53538,1.95113,-1.39347,-1.04652,0 -0.89767,1.02861,-1.33679,-1.17756,0 -0.17309,1.7205,-1.16677,-1.17756,0 -0.89767,1.7205,-1.28012,-1.17756,0 -0.53538,0.79798,-1.16677,-1.30859,0 -0.89767,1.48987,-1.28012,-1.04652,0 -1.50149,1.25924,-1.5635,-1.30859,0 -0.89767,0.56735,-1.16677,-0.91549,0 -1.25996,0.79798,-1.05341,-1.30859,0 -1.01844,-0.12454,-1.22344,-1.30859,0 -1.01844,0.79798,-1.22344,-1.04652,0 -0.77691,1.02861,-1.28012,-1.30859,0 -0.77691,0.79798,-1.33679,-1.30859,0 -1.38073,0.33672,-1.22344,-1.30859,0 -1.25996,0.10609,-1.22344,-1.30859,0 -0.53538,0.79798,-1.28012,-1.04652,0 -0.77691,2.41239,-1.28012,-1.43963,0 -0.41462,2.64302,-1.33679,-1.30859,0 -1.1392,0.10609,-1.28012,-1.43963,0 -1.01844,0.33672,-1.45015,-1.30859,0 -0.41462,1.02861,-1.39347,-1.30859,0 -1.1392,0.10609,-1.28012,-1.43963,0 -1.74302,-0.12454,-1.39347,-1.30859,0 -0.89767,0.79798,-1.28012,-1.30859,0 -1.01844,1.02861,-1.39347,-1.17756,0 -1.62225,-1.73895,-1.39347,-1.17756,0 -1.74302,0.33672,-1.39347,-1.30859,0 -1.01844,1.02861,-1.22344,-0.78446,0 -0.89767,1.7205,-1.05341,-1.04652,0 -1.25996,-0.12454,-1.33679,-1.17756,0 -0.89767,1.7205,-1.22344,-1.30859,0 -1.50149,0.33672,-1.33679,-1.30859,0 -0.65615,1.48987,-1.28012,-1.30859,0 -1.01844,0.56735,-1.33679,-1.30859,0 1.39683,0.33672,0.53351,0.26382,1 0.67225,0.33672,0.42016,0.39485,1 1.27607,0.10609,0.64686,0.39485,1 -0.41462,-1.73895,0.13678,0.13278,1 0.79301,-0.5858,0.47683,0.39485,1 -0.17309,-0.5858,0.42016,0.13278,1 0.55149,0.56735,0.53351,0.52588,1 -1.1392,-1.50832,-0.25995,-0.26032,0 0.91378,-0.35517,0.47683,0.13278,1 -0.77691,-0.81643,0.0801,0.26382,1 -1.01844,-2.43084,-0.1466,-0.26032,1 0.06843,-0.12454,0.25013,0.39485,1 0.1892,-1.96958,0.13678,-0.26032,1 0.30996,-0.35517,0.53351,0.26382,1 -0.29386,-0.35517,-0.08993,0.13278,1 1.03454,0.10609,0.36348,0.26382,1 -0.29386,-0.12454,0.42016,0.39485,1 -0.05233,-0.81643,0.19345,-0.26032,1 0.43072,-1.96958,0.42016,0.39485,1 -0.29386,-1.27769,0.0801,-0.12929,1 0.06843,0.33672,0.59018,0.78795,1 0.30996,-0.5858,0.13678,0.13278,1 0.55149,-1.27769,0.64686,0.39485,1 0.30996,-0.5858,0.53351,0.00175,1 0.67225,-0.35517,0.30681,0.13278,1 0.91378,-0.12454,0.36348,0.26382,1 1.1553,-0.5858,0.59018,0.26382,1 1.03454,-0.12454,0.70354,0.65692,1 0.1892,-0.35517,0.42016,0.39485,1 -0.17309,-1.04706,-0.1466,-0.26032,1 -0.41462,-1.50832,0.02343,-0.12929,1 -0.41462,-1.50832,-0.03325,-0.26032,1 -0.05233,-0.81643,0.0801,0.00175,1 0.1892,-0.81643,0.76021,0.52588,1 -0.53538,-0.12454,0.42016,0.39485,1 0.1892,0.79798,0.42016,0.52588,1 1.03454,0.10609,0.53351,0.39485,1 0.55149,-1.73895,0.36348,0.13278,1 -0.29386,-0.12454,0.19345,0.13278,1 -0.41462,-1.27769,0.13678,0.13278,1 -0.41462,-1.04706,0.36348,0.00175,1 0.30996,-0.12454,0.47683,0.26382,1 -0.05233,-1.04706,0.13678,0.00175,1 -1.01844,-1.73895,-0.25995,-0.26032,0 -0.29386,-0.81643,0.25013,0.13278,1 -0.17309,-0.12454,0.25013,0.00175,1 -0.17309,-0.35517,0.25013,0.13278,1 0.43072,-0.35517,0.30681,0.13278,1 -0.89767,-1.27769,-0.42998,-0.12929,0 -0.17309,-0.5858,0.19345,0.13278,1 0.55149,0.56735,1.27029,1.70519,1 -0.05233,-0.81643,0.76021,0.91899,1 1.51759,-0.12454,1.21362,1.18105,1 0.55149,-0.35517,1.04359,0.78795,1 0.79301,-0.12454,1.15694,1.31209,1 2.12141,-0.12454,1.61035,1.18105,1 -1.1392,-1.27769,0.42016,0.65692,1 1.75912,-0.35517,1.44032,0.78795,1 1.03454,-1.27769,1.15694,0.78795,1 1.63836,1.25924,1.32697,1.70519,1 0.79301,0.33672,0.76021,1.05002,1 0.67225,-0.81643,0.87356,0.91899,1 1.1553,-0.12454,0.98692,1.18105,1 -0.17309,-1.27769,0.70354,1.05002,1 -0.05233,-0.5858,0.76021,1.57416,1 0.67225,0.33672,0.87356,1.44312,1 0.79301,-0.12454,0.98692,0.78795,1 2.24217,1.7205,1.66703,1.31209,1 2.24217,-1.04706,1.78038,1.44312,1 0.1892,-1.96958,0.70354,0.39485,1 1.27607,0.33672,1.10027,1.44312,1 -0.29386,-0.5858,0.64686,1.05002,1 2.24217,-0.5858,1.66703,1.05002,1 0.55149,-0.81643,0.64686,0.78795,1 1.03454,0.56735,1.10027,1.18105,1 1.63836,0.33672,1.27029,0.78795,1 0.43072,-0.5858,0.59018,0.78795,1 0.30996,-0.12454,0.64686,0.78795,1 0.67225,-0.5858,1.04359,1.18105,1 1.63836,-0.12454,1.15694,0.52588,1 1.87988,-0.5858,1.32697,0.91899,1 2.4837,1.7205,1.497,1.05002,1 0.67225,-0.5858,1.04359,1.31209,1 0.55149,-0.5858,0.76021,0.39485,1 0.30996,-1.04706,1.04359,0.26382,1 2.24217,-0.12454,1.32697,1.44312,1 0.55149,0.79798,1.04359,1.57416,1 0.67225,0.10609,0.98692,0.78795,1 0.1892,-0.12454,0.59018,0.78795,1 1.27607,0.10609,0.93024,1.18105,1 1.03454,0.10609,1.04359,1.57416,1 1.27607,0.10609,0.76021,1.44312,1 -0.05233,-0.81643,0.76021,0.91899,1 1.1553,0.33672,1.21362,1.44312,1 1.03454,0.56735,1.10027,1.70519,1 1.03454,-0.12454,0.81689,1.44312,1 0.55149,-1.27769,0.70354,0.91899,1 0.79301,-0.12454,0.81689,1.05002,1 0.43072,0.79798,0.93024,1.44312,1 0.06843,-0.12454,0.76021,0.78795,1
聚类算法的具体思路为,创建iris类储存每一个iris对象,然后创建一个List<iris> data存放数据集,创建一个iris数组存放聚类中心,创建distance方法计算样本点和聚类中心的欧氏距离的平方,选取距离最短的将其投入该类。分类标签存放在iris中。每次结束后将聚类中心更新为该类中全部样本点的中值然后再重复以上过程知道前后两次的sse误差不超过0. 000001,认为聚类达到稳定,停止操作输出结果到文件。
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Kmeans {
ArrayList<iris> data = new ArrayList<iris>();
iris[] mean = new iris[10];
int[] quantity = new int[10];
int[] y=new int[10];
double sserror=0;
public static void main(String[] args) {
Kmeans km = new Kmeans();
//
km.creatdataset();
for(int k=1;k<10;k++) {
double s1 = km.start(k);
System.out.println("k="+k+"sse="+s1);
double tmp = (s1-595)*100;
km.y[k-1] = (100-(int)tmp)*10;
}
for(int i=0;i<9;i++)
System.out.println(km.y[i]);
km.plot();
km.start(2);
km.toFile();
}
void toFile() {
try {
File file = new File("C:\\Users\\hpcalc\\workspace\\1\\cluster.txt");
file.createNewFile();
DataOutputStream ds=new DataOutputStream(new FileOutputStream(file));
for(iris i:data) {
ds.writeBytes(i.toString()+"\n");
}
ds.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
void plot() {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(1000, 1000, 1000, 1000);// 窗体大小
window.setTitle("sse"); // 标题
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
void creatdataset() {
try {
BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\hpcalc\\workspace\\1\\src\\iris.csv"));
String str;
while((str=br.readLine())!=null) {
String[] a = str.split(",");
data.add(new iris(Double.parseDouble(a[0]),Double.parseDouble(a[1]),Double.parseDouble(a[2]),Double.parseDouble(a[3]),a[4]));
}
System.out.println(data);
}
catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
}
double start(int k) {
double sse;
int cnt=0;
for(int i=0;i<k;i++) {
mean[i] = data.get(i);
mean[i].group = i;
quantity[i] = 0;
}
double tmpsse=0.00001;
do {
cnt++;
/*for(int i=0;i<k;i++) {
System.out.println(mean[i]);
}*/
sse = tmpsse;
for(iris i:data) {
double d=9999;
for(int j = 0;j<k;j++) {
double tmpd = distance(i,mean[j]);
if(tmpd<d) {
i.group = j;
d = tmpd;
}
}
}
tmpsse = getsse();
iris[] mmean = new iris[10];
for(int i=0;i<k;i++) {
mmean[i] = new iris(0,0,0,0,mean[i].lable);
}
for(iris i:data) {
if(i!=null) {
quantity[i.group]++;
mmean[i.group].add(i);
}
}
for(int i=0;i<k;i++) {
mmean[i].div(quantity[i]);
}
mean = mmean;
//System.out.println(sse+","+tmpsse);
sserror = tmpsse/sse;
//System.out.println(sserror);
if(sserror>0.99999&&sserror<1.000001)
break;
}while(true);
return sse;
}
double distance(iris a,iris b) {
double d = Math.pow(a.a-b.a, 2)+Math.pow(a.b-b.b, 2)+Math.pow(a.c-b.c, 2)+Math.pow(a.d-b.d, 2);
return d;
}
double getsse(){
double sse=0;
for(iris i:data) {
sse+=distance(i,mean[i.group]);
}
return sse;
}
class MyCanvas extends JComponent {
public void paint(Graphics g) {
int[] x= {0,100,200,300,400,500,600,700,800};
g.drawPolyline(x,y,9);
}
}
}
class iris{
double a,b,c,d;
String lable;
int group;
iris(double parseDouble, double parseDouble2, double parseDouble3, double parseDouble4, String string) {
a = parseDouble;
b = parseDouble2;
c = parseDouble3;
d = parseDouble4;
lable = string;
}
public void add(iris t) {
this.a+=t.a;
this.b+=t.b;
this.c+=t.c;
this.d+=t.d;
}
public void div(int t) {
this.a/=t;
this.b/=t;
this.c/=t;
this.d/=t;
}
@Override
public String toString() {
return a+","+b+","+c+","+d+","+group;
}
}
通过本实验,复习了kmeans算法的实现,复习了内部类和io的知识点,学习了java绘图的基本操作,熟练了java代码的编写。在完成本实验的过程中仍有不足,对于随机选取点采用了取前k个点增加迭代次数补偿误差的方式,后续将尝试更换更加合理的选取初始聚类中心的方式。
实验六:
一个图书管理系统的面向对象设计方案如下图所示:
Book代表书,有”Name(书名)“、“Author(作者)”、”Price(价格)“、”IsBorrowed(是否借出)”四个属性。
类Library代表图书馆,其内部字段books用于保存图书馆中所有的书,他的FindBook()方法依据书名查找同名的书(可能有多本)。另一个Get AllBooks()方法获取馆藏所有书的详细信息。
类Reader代表作者,Name字段代表其姓名,读者可以进行BorrowBook()(借书),ReturnBook():(还书)操作。
请完成以下工作:
- 用Java编程实现以上三个类。
- 在main()方法内书写以下测试代码:
- 创建一个Library的类的实例,myLittleLibrary,其中预存有以下三本书:
Java程序设计,张三著,45元
Java核心设计,李四著,50元
Java程序设计,王五著,38元
- 显示图书馆所有图书的信息,输出样例如下:
Java程序设计,张三著,45元,可借
Java核心设计,李四著,50元,可借
Java程序设计,王五著,38元,未还
- 创建一个Reader类的实例oneBeautifulGril,她先在myLittleLibrary中查找《Java程序设计》;
- 当oneBeautifulGril借了张三著的那一本书时,显示当前图书馆所有图书的信息;
- oneBeautifulGril把书还了,再次显示图书馆中图书信息;
首先按照题目要求创建三个类,main方法放在Library类里。在图书馆类中创建按书名查找和展示全部书籍的方法;在Book类中创建初始化图书的构造器以及重写toString方法用于打印图书信息;在读者类中创建初始化用户名的构造器以及借书和还书两个方法。
图书馆的初始图书在Library类中直接通过两层括号的方式直接初始化。在main方法中,首先创建图书馆类myLittleLibrary,然后调用Get AllBooks方法展示图书馆所有图书的信息。输出如下:
然后创建读者实例oneBeautifulGril,在myLittleLibrary中查找图书,然后将找到的图书存放到SelectList中:
之后调用BorrowBook方法借走张三著的书,并将其存放到BorowList中,再次查询图书馆书目信息:
oneBeautifulGril把BorrowList中的书全部还了,再次显示图书馆中图书信息:
import java.util.*;
public class Library {
List<Book> books = new ArrayList<Book>(){{
add(new Book("Java程序设计","张三著",45));
add(new Book("Java核心设计","李四著",50));
add(new Book("Java程序设计","王五著",38));
System.out.println("Library实例创建完成");
}};
public static void main(String[] args) {
Library myLittleLibrary = new Library();
System.out.println("显示图书馆所有图书的信息:");
myLittleLibrary.Get_AllBooks();
Reader oneBeautifulGril = new Reader("oneBeautifulGril");
System.out.println("oneBeautifulGril在myLittleLibrary中查找《Java程序设计》;");
List<Book> SelectList = myLittleLibrary.FindBook("Java程序设计");
List<Book> BorrowList = new ArrayList<Book>();
//Book a=null;
for(Book i:SelectList) {
if(i.Author.equals("张三著")) {
oneBeautifulGril.BorrowBook(i);
BorrowList.add(i);
System.out.println("oneBeautifulGril在myLittleLibrary中借走了"+i.Author+"的《"+i.Name+"》");
}
}
System.out.println("显示当前图书馆所有图书的信息:");
myLittleLibrary.Get_AllBooks();
for(Book i:BorrowList) {
oneBeautifulGril.ReturnBook(i);
System.out.println("oneBeautifulGril把"+i.Name+"."+i.Author+"还了");
}
System.out.println("显示图书馆所有图书的信息:");
myLittleLibrary.Get_AllBooks();
}
public List<Book> FindBook(String bname) {
List<Book> tmp = new ArrayList<Book>();
for(Book i:books) {
if(i.Name.equals(bname)) {
tmp.add(i);
System.out.println(i);
}
}
return tmp;
}
public void Get_AllBooks() {
for(Book i:books) {
System.out.println(i);
}
}
}
class Book{
String Author;
boolean IsBorrowed;
String Name;
double Price;
Book(String a,String c,double d){
Author=c;
IsBorrowed=false;
Name=a;
Price=d;
}
@Override
public String toString() {
String ib;
if(IsBorrowed == true)
ib = "未还";
else
ib = "可借";
return Name+","+Author+","+(int)Price+"元"+","+ib;
}
}
class Reader{
String name;
Reader(String a){
name=a;
}
void BorrowBook(Book book) {
book.IsBorrowed = true;
}
void ReturnBook(Book book) {
book.IsBorrowed = false;
}
}
通过本实验,复习了List的用法,复习了List储存对象的实质是存放其地址,创建一个对象用“=”复制实际类似于C语言的指针的效果,在借还书的过程中用到了创建新的对象指向原有的实例的方法。复习了List初始化和删除元素的相关知识点。应对可能出现的作者名下存在多本书目的时候设置了查找和借书List来保证结果的正确。在完成本实验的过程中仍有不足,当前查找部分仅能保证完成题目所给的情况,对于书目较多的情况可能遍历查找的效率过低,后续将通过进一步学习提高查找的效率。