Java学习-节点2

第六天

自己编写一种容器

对比ArrayList,要求实现以下功能:
add(value)
add(value,index)
get(index)
clear()
erase(index)

1.首先容器是一种泛型工具,java中泛型跟C++差不多,直接拿来用就可以了。
2.思考ArrayList如何实现自动改变大小的功能。之前在C++的书上只说了容器会自动分配内存空间,并随着自身大小调节新分配的内存空间。
打开ArrayList源码,发现容器将内容都存储在数组中,不断在内存中分配一个大于现容量的固定数组,并重新为数组赋值,不断重复此过程从而实现容器的功能。
3.如何将泛型存入数组呢?java中无法创建泛型的数组,查看ArrayList源码,发现其利用了向上向下转型功能,将各类类型数组都统一为Object类型(java中所有类型都继承自Object),在存入时自动向上转型,在取出时自动向下转型。(尽量少使用向上转型,或总是跟向下转型成对出现)。
4.方法都知道了,开始实践。

package com.zht0109.mylist;

public class MyList<T>
{
public static int initLength=2; 
public int activitySize=0;

public int size=initLength;
private int growLength=initLength;
private Object[] elementData;
private Object[] value=new Object[initLength];


public T get(int index)
{
	if(index<0||index>activitySize-1)
	{
		System.out.println("超出范围");
		return null;
	}
	return (T)value[index];
}

public int size()
{
	return activitySize;
}

public void clear()
{
	value=new Object[initLength];
	activitySize=0;
	size=initLength;
	growLength=this.initLength;
}
public void show()
{
	for(int i=0;i<activitySize;i++)
	{
		System.out.println((T)value[i]);
	}
}

public void erase(int index)
{
	if(index<0||index>activitySize-1)
	{
		System.out.println("超出范围");
		return;
	}
	if(size-activitySize>2*growLength)
	{
		value=cut(index);
		growLength=calculationGrow();
	}
	else
	{
		Object[] tempValue=value;
		copy(tempValue,value,index+1,activitySize,-1);
	}
	--activitySize;
}

public void add(T data,int index)
{
	if(index<0||index>activitySize-1)
	{
		System.out.println("索引超出范围");
	}
	if (!checkSize(activitySize+1))
	{
		growLength=calculationGrow();
		value=grow(growLength,index);
	}
	value[index]=data;
	++activitySize;
}

public void add(T data)
{
	if (!checkSize(activitySize+1))
	{
		growLength=calculationGrow();
		value=grow(growLength);
	}
	value[activitySize]=data;
	++activitySize;
}

private boolean checkSize(int newsize)
{
	if (newsize>size||newsize<0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

private Object[] grow(int gl)
{
	Object[] tempValue=new Object[gl+size];
	copy(value,tempValue,0,value.length,0);
	size=gl+size;
	return tempValue;	
}

private Object[] grow(int gl,int index)
{
	Object[] tempValue=new Object[gl+size];
	copy(value,tempValue,0,index,0);
	copy(value,tempValue,index,value.length,1);
	size=gl+size;
	return tempValue;
}

private void copy(Object[] old,Object[] fresh,int begin,int end,int de)
{
	for(int n=begin;n<end;++n)
	{
		fresh[n+de]=old[n];
	}
}
private int calculationGrow()
{
	return Math.max((size-growLength)/2, 2);
}
private Object[] cut(int index)
{
	Object[] tempValue=new Object[activitySize-1];
	copy(value,tempValue,0,index,0);
	copy(value,tempValue,index+1,activitySize,-1);
	size=activitySize-1;
	return tempValue;
}

}

这其中每次growLength的大小可以自己设计方法调节,如果每次都只增长固定大小,则该容器很节省内存,但是运行速度慢。如果增长数目很大,程序运行快,但内存消耗大。
初始空间为2,Mylist与ArrayList进行运算速度比较如下:
MyList add程序运行时间: 879600ns
ArrayList add程序运行时间: 413400ns
MyList erase程序运行时间: 593800ns
ArrayList remove程序运行时间: 504000ns
将初始空间设置足够大,Mylist与ArrayList进行运算速度比较如下:
MyList add程序运行时间: 367300ns
ArrayList add程序运行时间: 361000ns
MyList erase程序运行时间: 505600ns
ArrayList remove程序运行时间: 516600ns
由于ArrayList源码无法修改,所以ArrayList始终是使用java容器的内存分配方法。
可以看出自己定义的MyList内存分配方式还是十分耗时的。
似乎ArrayList分配内存时参考了硬件中内存的区块进行分配,在add时每次ArrayList运行结果差异较大。

用时:3小时

第七天

重绘

在之前的画图板程序中,当窗口变动时,之前绘制的图案会消失,原因是该类只会向屏幕硬件发送一次性的数据,当缓存刷新后,原来的图案就会被覆盖。
JFrame中只刷新了元件的基础图案,该方法被写在JFrame的public void paint(Graphics g);如果我们想要实时重绘画图板的话,需要重写该函数。
于是自己定义一个新类,继承自JFrame,在paint中调用super并加入自己的代码。
重绘方法:
1.记录每一种基础图案的数据,并在paint中更新
2.记录每一次绘画的操作,并在paint中再次进行该操作

这两种方法都需要将需要保存的信息存入列表中,然后依次取出。我们可以为每一种对象都定义一个列表,也可以将这些对象同时继承自一个父类,只定义父类的列表。再取出时按照某种编码自行转换为需要的类型。

package com.zht0106.ProcessDraw;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

import javax.swing.JFrame;

public class MyFrame extends JFrame
{
static int paintMode=0;
ArrayList<Shape> lines=new ArrayList<Shape>();
ArrayList<Color> lineColors=new ArrayList<Color>();
ArrayList<Shape> rects=new ArrayList<Shape>();
ArrayList<Color> rectColors=new ArrayList<Color>();
ArrayList<Shape> ovals=new ArrayList<Shape>();
ArrayList<Color> ovalColors=new ArrayList<Color>();

ArrayList<Shape> shapes=new ArrayList<Shape>();
ArrayList<Short> codes=new ArrayList<Short>();
ArrayList<Color> shapeColors=new ArrayList<Color>();

ArrayList<Method> methods=new ArrayList<Method>();
ArrayList<Short> methodCodes=new ArrayList<Short>();
ArrayList<ArrayList<Color>> methodColors=new ArrayList<ArrayList<Color>>();
public void paint(Graphics g)
{
	super.paint(g);
	if (paintMode==0)
	{
		for(int i=0;i<lines.size();++i)
		{
			g.setColor(lineColors.get(i));
			int x1,y1,x2,y2;
			x1=((Line) lines.get(i)).x1;
			y1=((Line) lines.get(i)).y1;
			x2=((Line) lines.get(i)).x2;
			y2=((Line) lines.get(i)).y2;
			g.drawLine(x1,y1,x2,y2);
		}
		for(int i=0;i<rects.size();++i)
		{
			g.setColor(rectColors.get(i));
			int x,y,w,h;
			x=((Rect) rects.get(i)).x;
			y=((Rect) rects.get(i)).y;
			w=((Rect) rects.get(i)).w;
			h=((Rect) rects.get(i)).h;
			g.fillRect(x,y,w,h);
		}
		for(int i=0;i<ovals.size();++i)
		{
			g.setColor(ovalColors.get(i));
			int x,y,w,h;
			x=((Oval) ovals.get(i)).x;
			y=((Oval) ovals.get(i)).y;
			w=((Oval) ovals.get(i)).w;
			h=((Oval) ovals.get(i)).h;
			g.fillOval(x,y,w,h);
		}
	}
	else if(paintMode==1)
	{
		for(int i=0;i<shapes.size();++i)
		{
			if(codes.get(i)==Line.code)
			{
				((Line) shapes.get(i)).paint(shapeColo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值