Integer i = 128;
Integer b = 128;
Boolean b2= (i==b);
چرامقدار b2 در کد بالا false میباشد؟
همانند مکانیزم String pool. جاوا برای اعداد نیز مکانیزمی به نام Integer pool دارد و اعداد در بازه ی -۱۲۸ تا ۱۲۷ را کش میکند و اگر دوتا Integer به یکی از مقادیر در این بازه اشاره کنند درواقع هردو به یک خانه در حافظه اشاره میکنند .
به این دلیل خانه های حافظه ی آنها یکسان است
اما اگر به مقداری خارج از محدوده ی بالا اشاره کنند .. دیگر خانه های آنها یکسان نخواهد بود درنتیجه b2==false خواهد بود.
پس :
Integer i = 127;
Integer b = 127;
Boolean b2= (i==b);
در کد فوق b2 ترو خواهد بود
توجه کنید که اگر داشته باشیم :
Integer i = new Integer(128);
Integer b = 128;
Boolean b2= (i==b);
بی۲ فالس خواهد بود زیرا با new کردن ما مکانیزم کش را نادیده میگیریم.
این نکته قابل ذکر است که در primitive type ها این داستان های کشینگ را نداریم و در برابری بین دو int صرفا مقدار آن دو مقایسه میشود پس :
Integer i = 128;
Integer b = 128;
Boolean b2= (i==b.intValue());
در کد فوق b2 نیز true خواهد بود (با اینکه i و b به یک مکان در حافظه اشاره نمیکنند اما چون آنباکس میشوند صرفا مقدار آنها چک میشود)
@this_java
Integer b = 128;
Boolean b2= (i==b);
چرامقدار b2 در کد بالا false میباشد؟
همانند مکانیزم String pool. جاوا برای اعداد نیز مکانیزمی به نام Integer pool دارد و اعداد در بازه ی -۱۲۸ تا ۱۲۷ را کش میکند و اگر دوتا Integer به یکی از مقادیر در این بازه اشاره کنند درواقع هردو به یک خانه در حافظه اشاره میکنند .
به این دلیل خانه های حافظه ی آنها یکسان است
اما اگر به مقداری خارج از محدوده ی بالا اشاره کنند .. دیگر خانه های آنها یکسان نخواهد بود درنتیجه b2==false خواهد بود.
پس :
Integer i = 127;
Integer b = 127;
Boolean b2= (i==b);
در کد فوق b2 ترو خواهد بود
توجه کنید که اگر داشته باشیم :
Integer i = new Integer(128);
Integer b = 128;
Boolean b2= (i==b);
بی۲ فالس خواهد بود زیرا با new کردن ما مکانیزم کش را نادیده میگیریم.
این نکته قابل ذکر است که در primitive type ها این داستان های کشینگ را نداریم و در برابری بین دو int صرفا مقدار آن دو مقایسه میشود پس :
Integer i = 128;
Integer b = 128;
Boolean b2= (i==b.intValue());
در کد فوق b2 نیز true خواهد بود (با اینکه i و b به یک مکان در حافظه اشاره نمیکنند اما چون آنباکس میشوند صرفا مقدار آنها چک میشود)
@this_java
👍8
codeconventions-150003.pdf
128.9 KB
Don’t make any instance or class variable public without good reason. Often, instance
variables don’t need to be explicitly set or gotten—often that happens as a side effect of
method calls.
-Java code conventions
variables don’t need to be explicitly set or gotten—often that happens as a side effect of
method calls.
-Java code conventions
👍3
مقایسه ی Type wrapper ها و primitive type ها از نظر Performance
public static void main(String[] args) {
int repeats = 40000000;
long time;
time = System.currentTimeMillis();
long counterA = 0L;
for (int i = 0; i < repeats; i++) {
counterA = counterA + 4L;
}
System.out.println(counterA + " A: " + (System.currentTimeMillis() - time) + " ms");
time = System.currentTimeMillis();
Long counterB = 0L;
for (int i = 0; i < repeats; i++) {
counterB = counterB + 4L;
}
System.out.println(counterB + " B: " + (System.currentTimeMillis() - time) + " ms");
}
خروجی :
160000000 A: 0 ms
160000000 B: 284 ms
نتایج ممکن است با توجه به پردازنده, نسخه ی جاوا و... شما متفاوت باشد
دلیل نتایج فوق واضح است :
Type wrapper ها باید در heap
ذخیره شوند
و ساخت اشیا در heap هزینه ی بیشتری نسبت به stack دارد
بیاید کد بالا را بار دیگر , و اینبار به جای استفاده از autoboxing , از valueOf استفاده کنیم:
public static void main(String[] args) {
int repeats = 40000000;
long time;
time = System.currentTimeMillis();
long counterA = 0L;
for (int i = 0; i < repeats; i++) {
counterA = counterA + 4L;
}
System.out.println(counterA + " A: " + (System.currentTimeMillis() - time) + " ms");
time = System.currentTimeMillis();
Long counterB = Long.valueOf(0L);
for (int i = 0; i < repeats; i++) {
counterB = counterB + 4L;
}
System.out.println(counterB + " B: " + (System.currentTimeMillis() - time) + " ms");
}
خروجی :
160000000 A: 0 ms
160000000 B: 237 ms
دلیل این امر چیست؟
تعریف type wrapper به صورت بالا از نظر بایت کد تفاوت چندانی با تعریف به صورت زیر ندارد:
Long l = new Long(0L);
این کد همیشه یک شی جدید از Long با مقدار 0 ایجاد میکند . اما جاوا بصورت پیشفرض تعدادی از مقادیر پر استفاده را از اول اجرای برنامه ذخیره میکند تا تفاوت سرعت فاحشی میان primitive type و type wrapper بوجود نیاید :
@IntrinsicCandidate
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
با مشاهده ی متد valueOf (این متد را تحت عنوان static factory method میشناسیم)میتوان دید مقادیر -128 تا 127 کش شده اند .
و خارج از این محدوده , تفاوتی میان
Long l = 128L;
و
Long l = Long.valueOf(128L);
وجود ندارد.(البته لازم به ذکر است احتمالا اگر در برنامه ی شما یک عدد زیاد استفاده شود ان عدد نیز کش میشود)
البته استفاده از سازنده ی Long از نسخه ی 9 به بعد منسوخ شده و توسط جاوا پیشنهاد شده صرفا متد valueOf برای استفاده از Type wrapper ها به کار برده شود.
public static void main(String[] args) {
int repeats = 40000000;
long time;
time = System.currentTimeMillis();
long counterA = 0L;
for (int i = 0; i < repeats; i++) {
counterA = counterA + 4L;
}
System.out.println(counterA + " A: " + (System.currentTimeMillis() - time) + " ms");
time = System.currentTimeMillis();
Long counterB = 0L;
for (int i = 0; i < repeats; i++) {
counterB = counterB + 4L;
}
System.out.println(counterB + " B: " + (System.currentTimeMillis() - time) + " ms");
}
خروجی :
160000000 A: 0 ms
160000000 B: 284 ms
نتایج ممکن است با توجه به پردازنده, نسخه ی جاوا و... شما متفاوت باشد
دلیل نتایج فوق واضح است :
Type wrapper ها باید در heap
ذخیره شوند
و ساخت اشیا در heap هزینه ی بیشتری نسبت به stack دارد
بیاید کد بالا را بار دیگر , و اینبار به جای استفاده از autoboxing , از valueOf استفاده کنیم:
public static void main(String[] args) {
int repeats = 40000000;
long time;
time = System.currentTimeMillis();
long counterA = 0L;
for (int i = 0; i < repeats; i++) {
counterA = counterA + 4L;
}
System.out.println(counterA + " A: " + (System.currentTimeMillis() - time) + " ms");
time = System.currentTimeMillis();
Long counterB = Long.valueOf(0L);
for (int i = 0; i < repeats; i++) {
counterB = counterB + 4L;
}
System.out.println(counterB + " B: " + (System.currentTimeMillis() - time) + " ms");
}
خروجی :
160000000 A: 0 ms
160000000 B: 237 ms
دلیل این امر چیست؟
تعریف type wrapper به صورت بالا از نظر بایت کد تفاوت چندانی با تعریف به صورت زیر ندارد:
Long l = new Long(0L);
این کد همیشه یک شی جدید از Long با مقدار 0 ایجاد میکند . اما جاوا بصورت پیشفرض تعدادی از مقادیر پر استفاده را از اول اجرای برنامه ذخیره میکند تا تفاوت سرعت فاحشی میان primitive type و type wrapper بوجود نیاید :
@IntrinsicCandidate
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
با مشاهده ی متد valueOf (این متد را تحت عنوان static factory method میشناسیم)میتوان دید مقادیر -128 تا 127 کش شده اند .
و خارج از این محدوده , تفاوتی میان
Long l = 128L;
و
Long l = Long.valueOf(128L);
وجود ندارد.(البته لازم به ذکر است احتمالا اگر در برنامه ی شما یک عدد زیاد استفاده شود ان عدد نیز کش میشود)
البته استفاده از سازنده ی Long از نسخه ی 9 به بعد منسوخ شده و توسط جاوا پیشنهاد شده صرفا متد valueOf برای استفاده از Type wrapper ها به کار برده شود.
Oracle
Autoboxing and Unboxing (The Java™ Tutorials >
Learning the Java Language > Numbers and Strings)
Learning the Java Language > Numbers and Strings)
This beginner Java tutorial describes fundamentals of programming in the Java programming language
👍10
public static int fastExp(int base,int exponential){
if(exponential==0){
return 1;
} else if(exponential==1){
return base;
}
int R = fastExp(base,exponential/2);
if(exponential%2==0){
return R*R;
}
return R*base*R;
}
الگوریتم fast exponential
پیچیدگی زمانی:
O(lgn)
پیچیدگی زمانی الگوریتم معمولی :
O(n)
دسته بندی : Divide and conquer
@this_java
if(exponential==0){
return 1;
} else if(exponential==1){
return base;
}
int R = fastExp(base,exponential/2);
if(exponential%2==0){
return R*R;
}
return R*base*R;
}
الگوریتم fast exponential
پیچیدگی زمانی:
O(lgn)
پیچیدگی زمانی الگوریتم معمولی :
O(n)
دسته بندی : Divide and conquer
@this_java
👍4
Permutations of given array:
Subsets of given array:
public class Runner {
public static void main(String[] args) {
int a[]={1,2,3};
permutation(a,0);
}
private static void permutation(int[] a,int k) {
if(k==a.length-1){
System.out.println(Arrays.toString(a));
return;
}
for (int i = k; i <a.length; i++) {
int temp=a[k];
a[k]=a[i];
a[i]=temp;
permutation(a,k+1);
temp=a[k];
a[k]=a[i];
a[i]=temp;
}
}
}Subsets of given array:
public static void printSubSets(int arr[],int last,int k[]){
if(last==arr.length){
System.out.println(Arrays.toString(k));
return;
}int x = arr[last];
k[last] = x;
printSubSets(arr, last + 1, k);
k[last] = -1;
printSubSets(arr, last + 1, k);
}
public static void main(String[] args) {
int arr[]={1,2,3};
int k[]={-1,-1,-1};
printSubSets(arr,0,k);
}