View Full Version : مرتب کردن یک لیست از نوع آرایه
Restlesa
چهارشنبه 06 اردیبهشت 1396, 01:13 صبح
سلام به همگی
لیستی دارم که داده هایی که توش ذخیره میشن بصورت آرایه هستن در واقع یعنی زمان تعریف کردن لیست از دستور زیر استقاده کردم :
List<Object[]> ipList = ...
حال داده هایی که در داخل این لیست قرار میگیرن شامل آدرس IP به همراه شماره اندیسش در داخل دیتابیس هستش مثل عکس نمونه زیر :
145046
حال سوال من اینه که لیستی که در عکس بالا مشاهده می کنید رو به چه صورت می تونم بر اساس آدرس IP مرتب کنم ؟؟؟
vahid-p
چهارشنبه 06 اردیبهشت 1396, 02:47 صبح
شما آدرس ip ها رو به صورت یک String ذخیره کردید. من بودم به جای استفاده از 15 بایت برای ذخیره یک ip از نوع داده ای به صورت عددی استفاده میکردم. اینجوری الگوریتم sort اش هم سریعتر خواهد بود. البته همه اینها وقتی مهمه که لیستتون خیلی بزرگ باشه و اگر حجم زیادی نداره مهم نیست. به هر حال هر ip رو میشه به صورت یک عدد 4 بایتی (unsigned int) ذخیره کرد و فقط موقع نمایش به صورت xxx.xxx.xxx.xxx نمایشش داد. اما جاوا unsigned int نداره و باز یکم تغییراتی تو sort اش میخواد هر چند از نظر فضایی قابل ذخیره است. اما میتونید از 8 بایت استفاده کنید و از نوع داده ای long ذخیره کنید که در این صورت هیچ مشکلی ندارید و میتونید از توابع پیش تعریف شده Arrays.parallelSort() و Arrays.sort() استفاده کنید.
به هر حال اگر میخواهید به همین صورت مرتب کنید، فرمت کلی مرتب کردن یک آرایه به صورت زیر است (هم parallelsort هم sort):
Arrays.parallelSort(ipList,new Comparator<Object>(){ @Override
public int compare(Object o1, Object o2) {
String ip1=o1.getIP();
String ip2=o2.getIP();
//Compare two string ip1,ip2
//return 0; if they are the same
//return 1; if ip1 is bigger than ip2
//return -1; otherwise
}
});
اما میمونه قسمتی که //Compare two string ip1, ip2
این قسمت رو سعی کنید خودتون پیادش کنید. به این توجه کنید که مثلا اگر از سمت چپ دارید مقایسه میکنید، ممکنه یکی از ip ها یک رقمی باشه و یکی دو رقمی و یکی سه رقمی. که اگر فقط چک کنید کدوم کاراکتر بزرگتره مطمئنا به اشتباه جواب میدید 23 بزرگتر از 105 است! پس باید به طول عدد هم توجه کنید.
اگر نمیخواید در گیر اینا بشید و باز هم از String استفاده کنید میتونید به صورت مرتب سازی اسامی باهاش برخورد کنید (بهش میگن Lexicographical sort). در این صورت 23 بزرگتر از 105 است. اینکه بر چه اساسی مرتب بشه به نیازمندی شما بستگی داره.
در هر حال اگر براتون امکانش بود، بهتره از همون long برای ذخیره ip استفاده کنید.
Restlesa
پنج شنبه 07 اردیبهشت 1396, 00:11 صبح
اگه از long استفاده کنم چه طوری می تونم اونو به صورت یه آدرس IP به کاربر نمایش بدم
منظورم اینه که چه طوری اعداد رو از هم جدا کنم ؟؟؟ چه طوری باید بفهمم که منظورم از عدد 10331001 آدرس 10.33.100.1 هستش یا 103.3.100.1
vahid-p
پنج شنبه 07 اردیبهشت 1396, 02:00 صبح
خب مسلمه نباید long رو باز به عنوان یک رشته در نظر بگیرید و خود اون عددها رو قرار بدید. البته یه راه سادش اینه که همواره از سمت راست سه تا سه تا باشه. مثلا
10.33.100.1
رو به صورت 10033100001 ذخیره کنید که از راست سه تا سه تا جدا میکنید.
ولی چیزی که من میخواستم بگم هیچ کدوم از اینا نیست.
آی پی ورژن 4 همونطور که گفتم 4 بایت هست. اگر در مبنا 2 یا مثلا مبنا 16 بهش نگاه کنید ساده تر میشه.
اگر آی پی رو به صورت a.b.c.d در نظر بگیریم که هر کدوم از a تا d یک عدد بین 0 تا 255 هست، اونوقت عدد long برای ذخیره کردن آی پی به این صورت قابل ذخیره است:
int a = 10, b = 33, c = 100, d = 1;
long ip = (a << 24) | (b << 16) | (c << 8) | d;
System.out.println("Hex:" + Long.toString(ip, 16));
System.out.println("Dec:" + Long.toString(ip, 10));
System.out.println("Bin:" + Long.toString(ip, 2));
String ipStr = ((ip >> 24) & (0xFF)) +"."+
((ip >> 16) & (0xFF)) +"."+
((ip >> 8) & (0xFF)) +"."+
(ip & (0xFF));
System.out.println("IP:" + ipStr);
خروجی:
Hex:a216401
Dec:169960449
Bin:1010001000010110010000000001
IP:10.33.100.1
در کد بالا در خط 2 نحوه تبدیل به یک عدد long رو میبینید و در خط 4 به صورت عدد دهدهی. میبینید که هیچ شباهتی بین آی پی و عدد دهدهی نیست! ولی باینری رو اگر 8 تا 8 تا جدا کنید و هگزادسیمال را دو تا دو تا، به همون عددها در مبنای باینری و هگزادسیمال میرسید.
در قسمت ipStr هم عدد ip که از نوع long هست رو به یک رشته به فرمت IP تبدیل کردیم.
در خصوص << و >> که شیفت بیتی هستند اگر قبلا ندیدید سرچ کنید.
تنها کاری که لازمه انجام بدید اینکه هر ip که میخونید با split و تفکیک توسط "." اونها رو جدا و به عدد تبدیل کنید که با تابع Integer.valueOf به راحتی تبدیل میشه و...
vahid-p
پنج شنبه 07 اردیبهشت 1396, 15:31 عصر
این دو تابع رو میتونی برای تبدیل استفاده کنی: (با این فرض نوشتم که ورودی ها درست باشن و ورودی اشتباه نداشته باشه)
public static long toLong(String ip){
String[] nums=ip.split("\\.");
int a=Integer.valueOf(nums[0]);
int b=Integer.valueOf(nums[1]);
int c=Integer.valueOf(nums[2]);
int d=Integer.valueOf(nums[3]);
return (a << 24) | (b << 16) | (c << 8) | d;
}
public static String toString(Long ip){
return ((ip >> 24) & (0xFF)) +"."+
((ip >> 16) & (0xFF)) +"."+
((ip >> 8) & (0xFF)) +"."+
(ip & (0xFF));
}
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.