「装箱算法java」装箱算法最佳适合
本篇文章给大家谈谈装箱算法java,以及装箱算法最佳适合对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、java 什么是拆箱和装箱,拆箱和装箱 嘛用啊???
- 2、java 为什么要有装箱和拆箱?
- 3、java包装类怎样理解?装箱与拆箱又怎样理解?请通俗的解释一下,举个例子也行
- 4、装箱问题求解
- 5、求程序:装箱问题的近似算法--NF ( Next Fit ) 算法。谢谢帮助!
- 6、什么是Java自动拆装箱?
java 什么是拆箱和装箱,拆箱和装箱 嘛用啊???
详解Java的自动装箱与拆箱(Autoboxing and unboxing)
一、什么是自动装箱拆箱
很简单,下面两句代码就可以看到装箱和拆箱过程
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
下面我们来看看需要装箱拆箱的类型有哪些:
这个过程是自动执行的,那么我们需要看看它的执行过程:
public class Main {
public static void main(String[] args) {
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
}
}
反编译class文件之后得到如下内容:
javap -c StringTest
Integer total = 99;
执行上面那句代码的时候,系统为我们执行了:
Integer total = Integer.valueOf(99);
int totalprim = total;
执行上面那句代码的时候,系统为我们执行了:
int totalprim = total.intValue();
我们现在就以Integer为例,来分析一下它的源码:
1、首先来看看Integer.valueOf函数
public static Integer valueOf(int i) {
return i = 128 || i -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}
它会首先判断i的大小:如果i小于-128或者大于等于128,就创建一个Integer对象,否则执行SMALL_VALUES[i + 128]。
首先我们来看看Integer的构造函数:
private final int value;
public Integer(int value) {
this.value = value;
}
public Integer(String string) throws NumberFormatException {
this(parseInt(string));
}
它里面定义了一个value变量,创建一个Integer对象,就会给这个变量初始化。第二个传入的是一个String变量,它会先把它转换成一个int值,然后进行初始化。
下面看看SMALL_VALUES[i + 128]是什么东西:
private static final Integer[] SMALL_VALUES = new Integer[256];
它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。
所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
2、接着看看intValue函数
@Override
public int intValue() {
return value;
}
这个很简单,直接返回value值即可。
二、相关问题
上面我们看到在Integer的构造函数中,它分两种情况:
1、i = 128 || i -128 ===== new Integer(i)
2、i 128 i = -128 ===== SMALL_VALUES[i + 128]
private static final Integer[] SMALL_VALUES = new Integer[256];
SMALL_VALUES本来已经被创建好,也就是说在i = 128 || i -128是会创建不同的对象,在i 128 i = -128会根据i的值返回已经创建好的指定的对象。
说这些可能还不是很明白,下面我们来举个例子吧:
public class Main { public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); //true
System.out.println(i3==i4); //false
}
}
代码的后面,我们可以看到它们的执行结果是不一样的,为什么,在看看我们上面的说明。
1、i1和i2会进行自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内,它们会拿到SMALL_VALUES数组里面的同一个对象SMALL_VALUES[228],它们引用到了同一个Integer对象,所以它们肯定是相等的。
2、i3和i4也会进行自动装箱,执行了valueOf函数,它们的值大于128,所以会执行new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。
下面我们来看看另外一个例子:
public class Main { public static void main(String[] args) {
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2); //false
System.out.println(i3==i4); //false
}
}
看看上面的执行结果,跟Integer不一样,这样也不必奇怪,因为它们的valueOf实现不一样,结果肯定不一样,那为什么它们不统一一下呢?
这个很好理解,因为对于Integer,在(-128,128]之间只有固定的256个值,所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是对于Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。
总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
所以在Double里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。
public static Double valueOf(double d) {
return new Double(d);
}
下面我们进行一个归类:
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。
下面对Integer派别进行一个总结,如下图:
下面我们来看看另外一种情况:
public class Main { public static void main(String[] args) {
Boolean i1 = false;
Boolean i2 = false;
Boolean i3 = true;
Boolean i4 = true;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//true
}
}
可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
可以看到它并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
上面把几种情况都介绍到了,下面来进一步讨论其他情况。
Integer num1 = 400;
int num2 = 400;
System.out.println(num1 == num2); //true
说明num1 == num2进行了拆箱操作
Integer num1 = 100;
int num2 = 100;
System.out.println(num1.equals(num2)); //true
我们先来看看equals源码:
@Override
public boolean equals(Object o) {
return (o instanceof Integer) (((Integer) o).value == value);
}
我们指定equal比较的是内容本身,并且我们也可以看到equal的参数是一个Object对象,我们传入的是一个int类型,所以首先会进行装箱,然后比较,之所以返回true,是由于它比较的是对象里面的value值。
Integer num1 = 100;
int num2 = 100;
Long num3 = 200l;
System.out.println(num1 + num2); //200
System.out.println(num3 == (num1 + num2)); //true
System.out.println(num3.equals(num1 + num2)); //false
1、当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
2、对于num3.equals(num1 + num2)为false的原因很简单,我们还是根据代码实现来说明:
@Override
public boolean equals(Object o) {
return (o instanceof Long) (((Long) o).value == value);
}
它必须满足两个条件才为true:
1、类型相同
2、内容相同
上面返回false的原因就是类型不同。
Integer num1 = 100;
Ingeger num2 = 200;
Long num3 = 300l;
System.out.println(num3 == (num1 + num2)); //true
我们来反编译一些这个class文件:javap -c StringTest
可以看到运算的时候首先对num3进行拆箱(执行num3的longValue得到基础类型为long的值300),然后对num1和mum2进行拆箱(分别执行了num1和num2的intValue得到基础类型为int的值100和200),然后进行相关的基础运算。
我们来对基础类型进行一个测试:
int num1 = 100;
int num2 = 200;
long mum3 = 300;
System.out.println(num3 == (num1 + num2)); //true
上面就说明了为什么最上面会返回true.
所以,当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。
通过上面的分析我们需要知道两点:
1、什么时候会引发装箱和拆箱
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
我有一个微信公众号,经常会分享一些Java技术相关的干货文章,还有一些学习资源。
如果你需要的话,可以用微信搜索“Java团长”或者“javatuanzhang”关注。
java 为什么要有装箱和拆箱?
把一个基本类型包装成一个类,一个是可以使这个类型具有很多可以调用的方法。二个是Java向面像对象语言的靠近。其实Java还不算是很纯的面向对象的语言。真正的面向对象,是没有基本数据类型的。它只有一种类型,就是对象。三个是在泛型中,基本类型是不可以做泛型参数的。如:List int list = new ArrayListint ();这是不合法的。你只能这个样写ListInteger list = new ArrayListInteger ();也就是要用int型的包装类类型来解决基本类型不可以做泛型参数的问题 。
一名话,包装类有更多的方法和用途, 而这是基本类型没有的!!!
java包装类怎样理解?装箱与拆箱又怎样理解?请通俗的解释一下,举个例子也行
Java有一个类型系统有两个部分组成,包含基本类型(byte、char、int、short、long、float、double、boolean)和引用类型。而基本类型则对应着各自的引用类型,称为装箱的基本类型。而引用类型对应着各自的基本类型,称为拆箱的基本类型。对应的类型为:(Byte、Character、Integer、Short、Long、Float、Double、Boolean)
下面一具体例子来说明装箱与拆箱
//java 1.5之前创建一个Integer对象Integer i = new Integer(10);//java 1.5之后有了装箱的特性,直接用下列方式生成一个Integer对象//在这个过程中会将int 类型的10自动装箱成为Integer类型Integer i = 10;//拆箱 输出的值为20,这个过程中,会先将Integer类型的j自动拆箱为基本类型的10,最后完成运算Integer j = new Integer(10);int k = 10;
System.out.print(j+k);
装箱问题求解
实验一:32位整数的机器所能表示的整数范围大致是-20亿到+20亿,在这个范围内的操作一般不会出现问题。但是有很多应用程序可能要使用超出上述范围的整数。使用C++建立一个新的数据类型HugeInt,该类使用short integer[40]表示一个整数,其中一个数组元素表示十进制的一位。请实现该类。
实验二:某工厂有一名老板Boss,及若干工人。工人分为小时工HourlyWorker、计件工PieceWorker、销售员CommissionWorker。小时工每周工作40小时,超过40小时部分的报酬是平时的1.5倍;计件工是按生产的工件计算报酬的,每件的报酬是固定的,假设他只生产一种类型的工件;销售员每周有小部分固定的基本工资加上每周销售额的固定百分比;老板每周有固定的薪水。为该工厂设计一个简单的当前周的工资管理信息系统。要求如下:
1.设计实现一个简单的类Employee,它存储雇员的工号、姓(成员firstName)和名(成员lastName)。从雇员类Employee派生出小时工类HourlyWorker、计件工类PieceWorker、销售员类CommissionWorker及老板类Boss。
2.设计实现一个工厂类(Factory),它存储工厂名(factoryName)、工厂中的员工人数(含老板)等信息。及一个Employee指针数组存放工厂的所有员工信息。
3.可以增加一名工人。增加工人时,根据工人的类别,输入相应的信息。如增加的是小时工,则需要输入该小时工的工号、姓、名、本周工作小时数及每小时工资额等信息。
4.可以根据工号删除一名工人
5.可以根据工号修改工人的信息
6.可以显示出所有员工的本周工资信息
7.显示出一些统计信息,如本周支付所有员工的工资总额;小时工的工资总额、最高、最低、平均工资;计件工的工资总额、最高、最低、平均工资;销售员的工资总额、最高、最低、平均工资
实验三:装箱问题求解:设有编号为0、1、…、n-1的n种物品,体积分别为v0、v1、…、vn-1。将这n种物品装到容量都为V的若干箱子里。约定这n种物品的体积均不超过V,即对于0≤i<n,有0<vi≤V。不同的装箱方案所需要的箱子数目可能不同。装箱问题要求使装尽这n种物品的箱子数要少。算法思想:本实验可以使用贪婪法解决。该算法依次将物品放到它第一个能放进去的箱子中,该算法虽不能保证找到最优解,但还是能找到非常好的解。不失一般性,设n件物品的体积是按从大到小排好序的,即有v0≥v1≥…≥vn-1。如不满足上述要求,只要先对这n件物品按它们的体积从大到小排序,然后按排序结果对物品重新编号即可。装箱算法简单描述:
{ 输入箱子的容积;
输入物品种数n;
按体积从大到小顺序,输入各物品的体积;
预置已用箱子链为空;
预置已用箱子计数器box_count为0;
for (i=0;in;i++)
从已用的第一只箱子开始顺序寻找能放入物品i 的箱子j;
if(已用箱子都不能再放物品i)
{ 另用一个箱子,并将物品i放入该箱子;
box_count++;
}
else
将物品i放入箱子j;
}
}
上述算法能求出需要的箱子数box_count,并能求出各箱子所装物品。
若每只箱子所装物品用链表来表示,链表首结点指针存于一个结构中,该结构记录尚剩余的空间量和该箱子所装物品链表的首指针。另将全部箱子的信息也构成链表。下面两个结构分别表示物品和箱子结点。
struct Goods //物品
{ int no; //物品编号
int vol; //物品体积
struct Goods *next;//指向同一个箱子存放的下一个物品
};
struct Box //箱子
{ int remainder; //该箱子的剩余容量
struct Goods *head;//该箱子存放的物品链头指针
struct Box *next; //下一个已用箱子
};
问题补充:
回答好再加分
大哥顺便把后面两个也做了吧! 已经很感激了!
求程序:装箱问题的近似算法--NF ( Next Fit ) 算法。谢谢帮助!
看看这个思路怎么样,好像代码略多。
import java.util.Random;
import java.util.Scanner;
public class FillBox {
private Scanner scann;
private int objNum;
private int boxNum;
private int boxLength;
private Goods[] mGoods;
private Random random;
private Box[] mBox;
public FillBox(){
scann=new Scanner(System.in);
random=new Random();
objNum=getArgsFormConsol("请输入物品个数objNum:");
boxNum=getArgsFormConsol("请输箱子个数boxNum:");
boxLength=getArgsFormConsol("请输箱子长度(单位CM)boxLength:");
//设置物品数组
setGoodsArray(objNum,boxLength);
//设置箱子数组
setBoxAry(boxNum,boxLength);
//开始装箱子
doFillBox();
//物品的大小情况
showGoodsMessage();
//显示装箱情况
showBoxUse();
}
public static void main(String[] args){
new FillBox();
}
public int getArgsFormConsol(String pIntroduction){
System.out.print(pIntroduction);
int result=scann.nextInt();
System.out.println("***************\n");
return result;
}
public void setGoodsArray(int pNum,int pSize){
mGoods=new Goods[pNum];
for(int i=0;ipNum;i++){
int goodSize=pSize/4+random.nextInt(pSize/3);
Goods goods=new Goods(i,goodSize);
mGoods[i]=goods;
}
}
public void setBoxAry(int pTolNum,int pSize){
mBox=new Box[pTolNum];
for(int i=0;ipTolNum;i++){
Box aBox=new Box(i,pSize);
mBox[i]=aBox;
}
}
public void doFillBox(){//开支装箱子
int aBoxSpaceValue=boxLength;
int currentBoxId=0;
for(int i=0;imGoods.length;i++){
if(currentBoxId=boxNum){
System.out.println("已经没有足够的可用的箱子了!");
break;
}
Goods aGod=mGoods[i];
if(mGoods[i].getGoodsLength()=aBoxSpaceValue){
//装进这个箱子
mBox[currentBoxId].addGoods(aGod.getGoodsNum());
aBoxSpaceValue-=mGoods[i].getGoodsLength();
}else{
mBox[currentBoxId].setSpaceValue(aBoxSpaceValue);
aBoxSpaceValue=boxLength;//可用长度变长boxLength
currentBoxId++;
i--;//这个货物装不下了,换下一个箱子
}
}
}
public void showBoxUse(){
System.out.println("=====================\n下面是装箱详细情况:\n====================");
for(int i=0;iboxNum;i++){
System.out.println("\n"+mBox[i].getShow()+"\n* * * * * * * * * * * * * * *");
}
}
public void showGoodsMessage(){
for(int i=0;iobjNum;i++){
System.out.println("boxID:"+mGoods[i].getGoodsNum()+", box长度:"+mGoods[i].getGoodsLength());
}
}
}
public class Goods {
private int goodsNum;
private int goodsLength;
public Goods(){
}
public Goods(int pNum,int pLength){
this.goodsNum=pNum;
this.goodsLength=pLength;
}
public int getGoodsNum() {
return goodsNum;
}
public void setGoodsNum(int goodsNum) {
this.goodsNum = goodsNum;
}
public int getGoodsLength() {
return goodsLength;
}
public void setGoodsLength(int goodsLength) {
this.goodsLength = goodsLength;
}
}
import java.util.Vector;
public class Box {
private int boxNum;
private int boxLength;
private VectorInteger containGoodsID;
private int spaceValue;
public Box(){
}
public Box(int pNum,int pLength){
this.boxNum=pNum;
this.boxLength=pLength;
containGoodsID=new VectorInteger();
spaceValue=boxLength;
}
public int getBoxNum() {
return boxNum;
}
public void setBoxNum(int boxNum) {
this.boxNum = boxNum;
}
public int getBoxLength() {
return boxLength;
}
public void setBoxLength(int boxLength) {
this.boxLength = boxLength;
}
public void addGoods(Integer pGoodsID){
containGoodsID.add(pGoodsID);
}
public void removieGoods(Integer pGoodsID){
containGoodsID.removeElement(pGoodsID);
}
public int getSpaceValue() {
return spaceValue;
}
public void setSpaceValue(int spaceValue) {
this.spaceValue = spaceValue;
}
public String getShow(){
StringBuffer sb=new StringBuffer("箱子编号:"+this.boxNum+" 长度:"+this.boxLength+" 可用空间:"+spaceValue+"\n本箱子装的货物编号:");
for(int i=0;icontainGoodsID.size();i++){
sb.append(containGoodsID.get(i)+", ");
}
return sb.toString();
}
}
可能修饰性的代码比较多,关键逻辑就看doFill()了
什么是Java自动拆装箱?
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,double转化成double,等等。反之就是自动拆箱。
装箱算法java的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于装箱算法最佳适合、装箱算法java的信息别忘了在本站进行查找喔。