עבודה עם מספר שלם
כמחלקת עטיפה, Integer מספקת שיטות שונות לעבודה עם int , כמו גם מספר שיטות להמרת int למחרוזת ו- String ל- int . למחלקה יש שני בנאים:-
public Integer(int i) , כאשר i הוא ערך פרימיטיבי לאתחל. זה יוצר אובייקט שלם שמאוחל עם ערך int .
-
public Integer(String s) זורק NumberFormatException . כאן s הוא ייצוג מחרוזת של ערך int . בנאי זה יוצר אובייקט של מספר שלם שאותחל עם ערך int המסופק על ידי ייצוג מחרוזת .
יצירת אובייקט מספר שלם
ישנן אפשרויות שונות ליצירת אובייקטים שלמים . אחד הנפוצים ביותר בשימוש הוא הקל ביותר. הנה דוגמא:Integer myInteger = 5;
האתחול של המשתנה Integer במקרה זה דומה לאתחול של משתנה int הפרימיטיבי . אגב, אתה יכול לאתחל משתנה אינטגר עם הערך של int . הנה דוגמא:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
הפלט כאן הוא:
Integer myInteger = new Integer(5);
אתה יכול לעשות עם המשתנה Integer אותו דבר כמו עם int (להוסיף, להחסיר, להכפיל, לחלק, להגדיל, להפחית). עם זאת, חשוב לזכור שמספר שלם הוא סוג נתוני התייחסות, ומשתנה מסוג זה יכול להיות null. במקרה זה, עדיף להימנע מפעולות כאלה.
Integer myInteger1 = null;
Integer myInteger2 = myInteger1 + 5;
כאן נקבל חריג:
קבועי מחלקה שלמים
המחלקה 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 נכתבה במקור.
-
static Integer valueOf(int i) מחזיר מספר שלם שהערך שלו הוא i ;
-
סטטי Integer valueOf(String s) עובד כמו parseInt(String s) , אבל התוצאה תהיה Integer , לא int ;
-
static Integer valueOf(String s, int radix) עובד כמו parseInt(String s, int radix) , אבל התוצאה היא Intger , לא int .
האם יש בעיה עם מחלקה אינטגר? אה כן, יש…
אז ישנם שני סוגים של מספרים שלמים (שמתאימים ל-32 סיביות) ב-Java: int ו- Integer . כדי להבין את הפרטים של כל אחד מהם אנחנו צריכים לדעת את הדברים הבאים על מודל הזיכרון של JVM: כל מה שאתה מצהיר מאוחסן או ב-Stack Memory (JVM Stack ספציפי לכל Thread), או Heap Space. סוגים פרימיטיביים ( int , long , float , boolean , double , char , byte וכו') מאוחסנים בזיכרון Stack. כל האובייקטים והמערכים מאוחסנים ב-Heap Space. הפניות לאובייקטים ולמערכים הללו הדרושים לשיטות מאוחסנות ב-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 בתים:
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 בתים:
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 יותר!):
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[] !):
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;
}
התוצאות:
@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 ממערך של ערכי מסגרת ( מספר שלם ); כמעט פי שישה מהר יותר מ- ArrayList של ערכים מקופסת ( Ingeger s); ומהיר פי שניים מ- TIntArrayList (שלמעשה מקשט מערך של אינטס פרימיטיבי). לכן, אם אתה צריך מבנה נתונים כדי לאחסן אוסף של ערכים שלמים, והגודל שלו לא ישתנה, השתמש ב- int[] ; אם הגודל עומד להשתנות - אולי תרצה להשתמש בספריית tove4j עם TIntArrayList . והנה מגיע הסוף של החיבור שלי שבו אני מסביר את החסרונות של שימוש בסוג מספר שלם . יש כמה שיטות סטטיות מעניינות של Integer , שעלי לדבר עליהן לפני שאסיים. Public static Integer getInteger(מחרוזת nm, int val) לא עושה את מה שאפשר לחשוב, אלא מאחזר ערך Integer של מאפיין מערכת. Val הוא ברירת המחדל למקרה שמאפיין זה אינו מוגדר. public static String toBinaryString(int i) מחזירה מחרוזת עם ייצוג בינארי של מספר. ישנן שיטות לשליפה של ייצוגים מבוססי-16 ( toHexString ) ו-based-8 ( toOctalString ). יש שיטה לנתח מחרוזת לתוך int . גם אם המחרוזת היא ייצוג שאינו מבוסס על 10 רדיקסים. הנה כמה דוגמאות: Integer.parseInt("-FF", 16) מחזירה -255 Integer.parseInt("+42", 10) מחזירה 42 Integer.parseInt("1100110", 2) מחזירה 102
GO TO FULL VERSION