CodeGym /مدونة جافا /Random-AR /فئة Java.lang.Integer
John Squirrels
مستوى
San Francisco

فئة Java.lang.Integer

نشرت في المجموعة
يمكن تقسيم أنواع بيانات Java بشكل مشروط إلى كتلتين: بدائية ومرجعية (فئات). هناك العديد من أنواع البيانات البدائية في Java، مثل الأعداد الصحيحة ( byte ، short ، int ، long )، أرقام الفاصلة العائمة ( float ، double )، نوع البيانات المنطقية ( boolean ) ونوع بيانات الأحرف ( char ). من المحتمل أنك تعلم بالفعل أن كل نوع بيانات بدائي له فئة مجمعة خاصة به. نوع بيانات مرجعي "يلتف" أو يحول شقيقه الصغير البدائي في كائن Java. Integer عبارة عن فئة مجمعة لإخوانها البدائيين المسمى int. عدد صحيح باللغة الإنجليزية يعني عددا صحيحا. يمكن أن تكون موجبة أو سالبة أو 0. لسوء الحظ، العدد الصحيح في Java لا يعني أي رقم صحيح. العدد الصحيح في Java هو عدد صحيح يناسب 32 بت. إذا كنت تريد رقمًا أكبر، فنحن نرحب بك لاستخدام أرقام Java الطويلة . لديهم 64 بت تحت تصرفهم. إذا لم تكن محظوظًا بما يكفي لتحتاج إلى رقم أكبر، فقد قمت بتغطيته باستخدام BigInteger .

العمل مع عدد صحيح

كفئة مجمعة، توفر Integer طرقًا مختلفة للعمل مع int ، بالإضافة إلى عدد من الطرق لتحويل int إلى String و String إلى int . يحتوي الفصل على منشئين:
  • عدد صحيح عام (int i) ، حيث i هي قيمة بدائية للتهيئة. يقوم هذا بإنشاء كائن عدد صحيح تتم تهيئته بقيمة int .

  • عدد صحيح عام (سلسلة) يطرح NumberFormatException . هنا s هو تمثيل سلسلة لقيمة int . يقوم هذا المُنشئ بإنشاء كائن عدد صحيح تمت تهيئته باستخدام قيمة int التي يوفرها تمثيل السلسلة .

إنشاء كائن عدد صحيح

هناك خيارات مختلفة لإنشاء كائن عدد صحيح . أحد أكثر الطرق استخدامًا هو الأسهل. هنا مثال:
Integer myInteger = 5;
تشبه تهيئة المتغير الصحيح في هذه الحالة تهيئة المتغير int البدائي . بالمناسبة يمكنك تهيئة متغير Integer بقيمة int . هنا مثال:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
الإخراج هنا هو:
5
في الواقع، هنا يمكننا ملاحظة التعبئة التلقائية. يمكننا أيضًا إنشاء كائن عدد صحيح تمامًا مثل أي كائنات أخرى باستخدام مُنشئ وكلمة رئيسية جديدة :
Integer myInteger = new Integer(5);
يمكنك أن تفعل مع المتغير الصحيح نفس الشيء كما هو الحال مع int (إضافة، طرح، ضرب، قسمة، زيادة، إنقاص). ومع ذلك، من المهم أن تتذكر أن Integer هو نوع بيانات مرجعي، ويمكن أن يكون المتغير من هذا النوع خاليًا. وفي هذه الحالة الأفضل الامتناع عن مثل هذه العمليات.
Integer myInteger1  = null;
Integer myInteger2 = myInteger1 + 5;
هنا سنحصل على استثناء:
استثناء في الموضوع الرئيسي "java.lang.NullPointerException"

ثوابت فئة عدد صحيح

توفر فئة Integer ثوابت وأساليب مختلفة للتعامل مع الأعداد الصحيحة. ها هم:
  • الحجم يعني عدد البتات في نظام الأرقام المكون من رقمين الذي يشغله النوع 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 . تشير معلمة الجذر إلى أن نظام الأرقام قد تمت كتابته في الأصل.

بالإضافة إلى parseInt ، هناك أيضًا طريقة valueOf مشابهة جدًا في العديد من الأشكال. ومع ذلك، فإن نتيجة valueOf ستكون Integer ، و parseInt ستكون int .
  • static Integer valueOf(int i) يُرجع عددًا صحيحًا قيمته i ؛

  • تعمل قيمة عدد صحيح ثابت (String s) مثل parseInt(String s) ولكن النتيجة ستكون عدد صحيح وليس int ؛

  • تعمل قيمة عدد صحيح ثابت (String s, int radix) بنفس طريقة parseInt(String s, int radix) ، ولكن النتيجة هي عدد صحيح ، وليس int .

هل هناك أي مشكلة مع فئة عدد صحيح؟ اه نعم هناك…

لذلك هناك نوعان من الأعداد الصحيحة (التي تتناسب مع 32 بت) في Java: int و Integer . لفهم تفاصيل كل منها، نحتاج إلى معرفة ما يلي حول نموذج ذاكرة JVM: يتم تخزين كل ما تعلن عنه إما في Stack Memory (JVM Stack خاص بكل مؤشر ترابط)، أو Heap Space. يتم تخزين الأنواع البدائية ( int ، long ، float ، boolean ، double ، char ، byte ، إلخ) في ذاكرة Stack. يتم تخزين كافة الكائنات والمصفوفات في مساحة الكومة. يتم تخزين المراجع إلى هذه الكائنات والمصفوفات اللازمة للطرق في Stack. لذا. لماذا نهتم؟ حسنًا، كما ترى، Stack أصغر من Heap (خدعة)، ولكن تخصيص القيم في 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 (رأس الكائن: الفئة) 0x000492a0 12 4 int Integer.value 1 حجم المثيل: 16 بايت
ماذا؟! هذه ذاكرة أكبر بأربع مرات! ولكن دعونا لا نتوقف عند هذا الحد. كمطورين لـ Java، لا نتوقف عادةً عن استخدام عدد صحيح واحد. ما نريده حقًا هو استخدام الكثير منهم. كما هو الحال في التسلسل. على سبيل المثال، في مصفوفة. أو قائمة. يتم تخزين المصفوفات في الكومة، كما هو الحال مع القوائم. لذلك، يجب أن يستغرق التخصيص نفس القدر من الوقت تقريبًا. يمين؟ ولكن ماذا لو كنا بحاجة إلى تخصيص المزيد من الذاكرة؟ دعونا نتحقق من مقدار المساحة التي تشغلها مجموعة مكونة من 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 (رأس الكائن: علامة) 0x0000000000000001 (غير متحيز؛ العمر: 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 البصمة: 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> يشغل مساحة ذاكرة أكبر بأربعة أضعاف. هذا ليس جيدا. لكن لا تزال القوائم أسهل لأنه يمكننا إضافة العناصر وحذفها! يا جافا… لماذا تحتاج إلى وضع كل شيء في صندوق؟! لكنني نسيت أن Java رائعة، وعظمتها تكمن في وفرة المكتبات مفتوحة المصدر التي يمكننا استخدامها! 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 مرات. وهذا لا يتضمن مثيلات صحيحة . فقط كثافة العمليات. نحن مطورو Java نهتم حقًا بالذاكرة... ولكننا نهتم أيضًا بالأداء. توجد مكتبة رائعة للعلامات الدقيقة تحمل اسمًا متواضعًا 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;
}
النتائج:
رئيسي: test.SampleJavaBenchmark.testBoxedIntegersSum 5693337.344 ±(99.9%) 1198774.178 ops/s [المتوسط] (min, avg, max) = (1092314.989, 5693337.344, 12001683.428), stdev = 242 1583.144 سي (99.9%): [4494563.166, 6892111.522] (يفترض التوزيع الطبيعي) الرئيسي: test.SampleJavaBenchmark.testPrimitiveIntegersSum 15295010.959 ±(99.9%) 2555447.456 ops/s [Average] (min, avg, max) = (4560097.059, 15295010.959, 24283809.44 7)، ستيف = 5162130.283 سي (99.9٪): [12739563.502، 17850458.415] (يفترض التوزيع الطبيعي)
لذلك، في المتوسط، يكون تخصيص ومجموع الأعداد الصحيحة الأولية أسرع مرتين من الأعداد الصحيحة المعبأة. الآن، دعونا نقارن أداء الإنشاء وحساب مجموع المجموعات (أو صفائف مكونة من 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]
النتائج: مصفوفة الأوليات أسرع بأكثر من 4 مرات من مصفوفة القيم المعبأة ( Integer s)؛ أسرع بست مرات تقريبًا من ArrayList للقيم المعبأة ( Integer s)؛ وأسرع مرتين من TIntArrayList (الذي يزين في الواقع مجموعة من ints البدائية). لذلك، إذا كنت بحاجة إلى بنية بيانات لتخزين مجموعة من القيم الصحيحة، ولن يتغير حجمها، فاستخدم int [] ؛ إذا كان الحجم سيتغير — فقد ترغب في استخدام مكتبة tove4j مع TIntArrayList . وهنا تأتي نهاية مقالتي حيث أشرح سلبيات استخدام النوع الصحيح . هناك بعض الأساليب الثابتة المثيرة للاهتمام لـ Integer ، والتي يجب أن أتحدث عنها قبل أن أنتهي. عدد صحيح ثابت عام getInteger(String nm, int val) لا يفعل ما قد يظنه المرء، ولكنه يسترد قيمة عدد صحيح لخاصية النظام. Val هو الإعداد الافتراضي في حالة عدم تعيين هذه الخاصية. تقوم السلسلة الثابتة العامة toBinaryString(int i) بإرجاع سلسلة ذات تمثيل ثنائي لرقم. هناك طرق لاسترجاع التمثيلات المستندة إلى 16 ( toHexString ) و المستندة إلى 8 ( 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