CodeGym /وبلاگ جاوا /Random-FA /Java.lang.کلاس Integer
John Squirrels
مرحله
San Francisco

Java.lang.کلاس Integer

در گروه منتشر شد
انواع داده های جاوا را می توان به طور مشروط به دو بلوک تقسیم کرد: ابتدایی و مرجع (کلاس ها). چندین نوع داده ابتدایی در جاوا وجود دارد، مانند اعداد صحیح ( بایت ، کوتاه ، int ، طولانی )، اعداد ممیز شناور ( شناور ، دو برابر )، نوع داده منطقی ( بولی ) و نوع داده کاراکتر ( char ). احتمالاً قبلاً می دانستید که هر نوع داده اولیه دارای کلاس wrapper خاص خود است. یک نوع داده مرجع که برادر کوچک اولیه خود را در یک شی جاوا "پیچیده" یا تبدیل می کند. Integer یک کلاس wrapper برای برادر اولیه خود به نام int است. عدد صحیح در زبان انگلیسی به معنای عدد کامل است. آنها می توانند مثبت، منفی یا 0 باشند. متأسفانه، Integer در جاوا به معنای هیچ عدد کامل نیست. عدد صحیح در جاوا یک عدد کامل است که در 32 بیت قرار می گیرد. اگر عدد بزرگ‌تری می‌خواهید، می‌توانید از اعداد جاوا Long استفاده کنید . آنها 64 بیت در اختیار دارند. اگر به اندازه کافی بدشانس هستید که به تعداد بیشتری نیاز دارید، جاوا شما را با BigInteger پوشش داده است .

کار با عدد صحیح

به عنوان یک کلاس wrapper، Integer متدهای مختلفی را برای کار با int و همچنین تعدادی روش برای تبدیل int به String و String به int ارائه می‌کند . کلاس دو سازنده دارد:
  • public Integer(int i) که i یک مقدار اولیه برای مقداردهی اولیه است. این یکی یک شی عدد صحیح ایجاد می کند که با مقدار int مقداردهی اولیه می شود .

  • عمومی Integer(String s) NumberFormatException را می اندازد . در اینجا s یک نمایش رشته ای از مقدار int است . این سازنده یک شی عدد صحیح ایجاد می کند که با مقدار int ارائه شده توسط نمایش رشته مقداردهی اولیه شده است .

ایجاد شی عدد صحیح

گزینه های مختلف ایجاد شی عدد صحیح وجود دارد . یکی از پرکاربردترین آنها ساده ترین است. به عنوان مثال:
Integer myInteger = 5;
مقداردهی اولیه متغیر Integer در این مورد مشابه مقداردهی اولیه متغیر int اولیه است . به هر حال شما می توانید یک متغیر Integer را با مقدار int مقداردهی اولیه کنید . به عنوان مثال:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
خروجی در اینجا این است:
5
در واقع، در اینجا می توانیم بسته بندی خودکار را مشاهده کنیم. همچنین می‌توانیم یک شیء Integer درست مانند هر شیء دیگری با استفاده از سازنده و کلمه کلیدی جدید ایجاد کنیم :
Integer myInteger = new Integer(5);
می توانید با متغیر Integer مانند int (جمع، تفریق، ضرب، تقسیم، افزایش، کاهش) را انجام دهید. با این حال، مهم است که به یاد داشته باشید که Integer یک نوع داده مرجع است و متغیری از این نوع می تواند null باشد. در این صورت بهتر است از انجام چنین عملیاتی خودداری کنید.
Integer myInteger1  = null;
Integer myInteger2 = myInteger1 + 5;
در اینجا یک استثنا خواهیم داشت:
استثنا در موضوع "اصلی" java.lang.NullPointerException"

ثابت های کلاس صحیح

کلاس Integer ثابت ها و روش های مختلفی را برای کار با اعداد صحیح ارائه می دهد. آن ها اینجا هستند:
  • SIZE به معنای تعداد بیت های موجود در سیستم اعداد دو رقمی است که توسط نوع int اشغال شده است

  • BYTES تعداد بایت های سیستم اعداد دو رقمی است که توسط نوع int اشغال شده است

  • MAX_VALUE حداکثر مقداری است که نوع int می تواند نگه دارد

  • MIN_VALUE حداقل مقداری است که نوع int می تواند نگه دارد

  • TYPE یک شی از نوع Class را از نوع int برمی گرداند

مفیدترین روش های کلاس صحیح

حالا بیایید نگاهی اجمالی به متدهای پرکاربرد کلاس Integer داشته باشیم . گمان می‌کنم محبوب‌ترین آنها روش‌هایی برای تبدیل یک عدد از یک رشته یا بالعکس است.
  • static int parseInt(String s) این متد String را به int تبدیل می کند . اگر تبدیل امکان پذیر نباشد، NumberFormatException پرتاب می شود.

  • static int parseInt(String s, int radix) این روش همچنین پارامتر s را به int تبدیل می کند . پارامتر radix نشان می دهد که سیستم اعداد s در ابتدا نوشته شده است.

علاوه بر parseInt ، یک متد valueOf بسیار مشابه در چندین تغییر نیز وجود دارد . با این حال، نتیجه valueOf عدد صحیح خواهد بود و parseInt int خواهد بود .
  • static Integer valueOf(int i) یک عدد صحیح را برمی گرداند که مقدار آن i است .

  • static Integer valueOf(String s) مانند parseInt(String s) عمل می کند ، اما نتیجه عدد صحیح خواهد بود نه int .

  • static Integer valueOf(string s, int radix) مانند parseInt (رشته s، int radix) کار می کند ، اما نتیجه یک عدد صحیح است ، نه یک int .

آیا کلاس Integer مشکلی دارد؟ اوه بله وجود دارد…

بنابراین دو نوع برای اعداد صحیح (که در 32 بیت قرار می گیرند) در جاوا وجود دارد: int و Integer . برای درک ویژگی‌های هر یک از آنها، باید موارد زیر را در مورد مدل حافظه JVM بدانیم: هر چیزی که شما اعلام می‌کنید یا در حافظه پشته (پشته JVM مختص هر Thread) یا Heap Space ذخیره می‌شود. انواع اولیه ( int ، long ، float ، boolean ، double ، char ، byte و غیره) در حافظه Stack ذخیره می شوند. همه اشیا و آرایه ها در Heap Space ذخیره می شوند. ارجاع به این اشیاء و آرایه های مورد نیاز برای متدها در Stack ذخیره می شوند. بنابراین. چرا ما اهمیت می دهیم؟ خوب، می بینید که Stack از Heap کوچکتر است (یک con)، اما تخصیص مقادیر در Stack بسیار سریعتر از Heap (یک حرفه ای) است. بیایید با یک نوع اولیه int شروع کنیم . دقیقا 32 بیت طول می کشد. یعنی 32/8=4 بایت. زیرا از نوع بدوی است. حالا بیایید عدد صحیح را در نظر بگیریم . این یک شی است، با سربار و ترازهای اضافی. من از jol کتابخانه ای برای اندازه گیری اندازه آن استفاده کرده ام:
public static void main(String[] args) {
 	System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
و معلوم شد که 16 بایت اشغال می کند:
موارد داخلی java.lang.Integer شیء: OFF SZ TYPE DESCRIPTION VALUE 0 8 (سرصفحه شی: علامت) 0x000000748c90e301 (هش: 0x748c90e3؛ سن: 0) 8 4 (سرصفحه شی: کلاس 104920 in. اندازه: 16 بایت
چی؟! یعنی 4 برابر حافظه بیشتر! اما اجازه دهید به همین جا بسنده نکنیم. به عنوان توسعه دهندگان جاوا، ما معمولاً استفاده از یک عدد صحیح را متوقف نمی کنیم. آنچه ما واقعاً می خواهیم این است که از تعداد زیادی از آنها استفاده کنیم. مثل یک سکانس. به عنوان مثال، در یک آرایه. یا یک لیست آرایه ها مانند لیست ها در Heap ذخیره می شوند. بنابراین، تخصیص باید تقریباً به همان مقدار زمان ببرد. درست؟ اما اگر نیاز به تخصیص حافظه بیشتری داشته باشیم چه؟ بیایید بررسی کنیم که یک آرایه از 1000 مقدار int اولیه چقدر فضا می گیرد:
public static void main(String[] args) {
    	int[] array = new int[1000];
    	for (int i = 0; i < 1000; i++) array[i] = i;                System.out.println(ClassLayout.parseInstance(array).toPrintable());
}
و نتیجه 4016 بایت است:
OFF SZ نوع توضیحات مقدار 0 8 (عنوان شی: علامت گذاری) 0x000000000000000001 (غیر مغایر ؛ سن: 0) 8 4 (هدر شی: کلاس) 0x00006C38 12 4 (طول آرایه) 1000 12 4 (تراز/شکاف شکاف) 16 4000 int [I.< Elements> N/A اندازه نمونه: 4016 بایت تلفات فضا: 4 بایت داخلی + 0 بایت خارجی = 4 بایت کل
خوب، این به نوعی منطقی است، با توجه به اینکه یک int تنها 4 بایت طول می کشد. در مورد ArrayList<Integer> از 1000 عدد صحیح چطور ؟ بیایید نگاهی بیندازیم:
public static void main(String[] args) {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
      System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
و نتیجه 20040 بایت است (باز هم 4 برابر بیشتر!):
java.util.ArrayList@66d3c617d footprint: COUNT AVG SUM DESCRIPTION 1 4016 4016 [Ljava.lang.Object; 1000 16 16000 java.lang.Integer 1 24 24 java.util.ArrayList 1002 20040 (مجموع)
بنابراین، ArrayList<Integer> 4 برابر فضای حافظه بیشتری را اشغال می کند. این خوب نیست. اما با این حال، لیست ها آسان تر هستند زیرا می توانیم عناصر را اضافه و حذف کنیم! آه جاوا... چرا باید همه چیز را جعبه کنی؟! اما، فراموش می کنم، جاوا عالی است، و عظمت آن در فراوانی کتابخانه های منبع باز است که می توانیم استفاده کنیم! Trove4j یکی از آنهاست. دارای TINTArrayList است که در داخل دارای داده‌های int[] است . بیایید اندازه آن را اندازه گیری کنیم:
public static void main(String[] args) {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
و نتیجه 4040 بایت است (تقریباً همان int[] !):
gnu.trove.list.array.TIntArrayList@7440e464d: COUNT AVG SUM DESCRIPTION 1 4016 4016 [I 1 24 24 gnu.trove.list.array.TIntArrayList 2 4040 (مجموع)
بنابراین، در نهایت، ما می توانیم بهترین های هر دو جهان را داشته باشیم! لیستی از اعداد صحیح که 4 برابر فضای کمتری اشغال می کنند. و این شامل موارد Integer نیست . فقط int s. ما توسعه دهندگان جاوا واقعاً به حافظه اهمیت می دهیم ... اما به عملکرد نیز اهمیت می دهیم. یک کتابخانه microbenchmarking فوق العاده با نام ساده jmh وجود دارد که به ما امکان می دهد عملکرد کد را اندازه گیری کنیم. ابتدا اجازه دهید عملکرد محاسبه مجموع دو عدد صحیح تصادفی را با هم مقایسه کنیم: پیکربندی برای jmh به شرح زیر است:
benchmark {
	configurations {
    	main {
        	warmups = 5 // number of warmup iterations
        	iterations = 50 // number of iterations
        	iterationTime = 500 // time in seconds per iteration
        	iterationTimeUnit = "ns" // time unit for iterationTime
معیارها:
private static final Random random = new Random();

@Benchmark
public int testPrimitiveIntegersSum() {
	int a = random.nextInt();
	int b = random.nextInt();
	return a + b;
}

@Benchmark
public Integer testBoxedIntegersSum() {
	Integer a = random.nextInt();
	Integer b = random.nextInt();
	return a + b;
}
نتایج:
main: test.SampleJavaBenchmark.testBoxedIntegersSum 5693337.344 ±(99.9%) 1198774.178 عملیات در ثانیه [میانگین] (دقیقه، میانگین، حداکثر) = (1092314.989، 56933338، 56934338 = 56934337 st. 1583.144 CI (99.9%): [4494563.166, 6892111.522] (توزیع نرمال را فرض می کند) اصلی: test.SampleJavaBenchmark.testPrimitiveIntegersSum 15295010.959 ±(99.9%) 2555447.456 ops/s [میانگین] (دقیقه، میانگین، حداکثر) = (4560097.295010.295، 4560097.059،2901، 4560097.059.059. 7)، stdev = 5162130.283 CI (99.9٪): [12739563.502، 17850458.415] (توزیع نرمال را فرض می کند)
بنابراین، به طور متوسط، تخصیص و مجموع int های اولیه بیش از دو برابر سریعتر از اعداد صحیح جعبه ای است. حال، بیایید عملکرد ایجاد و محاسبه مجموع مجموعه ها (یا آرایه های 1000 اینتی اعداد صحیح) را با هم مقایسه کنیم:
@Benchmark
public int testPrimitiveArray() {
	int[] array = new int[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
11933.545 ops/s [Average]


@Benchmark
public int testBoxesArray() {
	Integer[] array = new Integer[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
2733.312 ops/s [Average]


@Benchmark
public int testList() {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int x : list) sum += x;
	return sum;
}
2086.379 ops/s [Average]


@Benchmark
public int testTroveIntList() {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int i = 0; i < 1000; i++) sum += list.get(i);
	return sum;
}
5727.979 ops/s [Average]
نتایج: آرایه primitives بیش از 4 برابر سریعتر از آرایه مقادیر جعبه شده است ( S ). تقریباً شش برابر سریعتر از ArrayList از مقادیر کادر بندی شده ( عدد صحیح ). و دو برابر سریعتر از TIntArrayList (که در واقع آرایه ای از int های اولیه را تزئین می کند). بنابراین، اگر به یک ساختار داده برای ذخیره مجموعه ای از مقادیر صحیح نیاز دارید و اندازه آن تغییر نمی کند، از یک int[] استفاده کنید . اگر اندازه قرار است تغییر کند - ممکن است بخواهید از کتابخانه tove4j با TIntArrayList استفاده کنید . و در اینجا به پایان مقاله من می رسد که در آن معایب استفاده از نوع Integer را توضیح می دهم . چند روش استاتیک جالب از Integer وجود دارد که قبل از اتمام باید در مورد آنها صحبت کنم. عمومی static Integer getInteger (string nm، int val) آن چیزی را که ممکن است فکر کنید انجام نمی دهد، اما یک مقدار Integer از ویژگی سیستم را بازیابی می کند. در صورتی که این ویژگی تنظیم نشده باشد، Val پیش فرض است. Public Static String toBinaryString(int i) یک رشته را با نمایش دودویی یک عدد برمی گرداند. روش‌هایی برای بازیابی نمایش‌های مبتنی بر ۱۶ ( toHexString ) و مبتنی بر ۸ ( toOctalString ) وجود دارد. روشی برای تجزیه رشته به int وجود دارد . حتی اگر رشته یک نمایش مبتنی بر ریشه 10 نباشد. در اینجا چند مثال آورده شده است: Integer.parseInt("-FF", 16) -255 Integer.parseInt("+42", 10) 42 Integer.parseInt("1100110", 2) را برمی گرداند 102
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION