Source code: com/sonalb/Utils.java
1 /*
2 * -*- mode: java; c-basic-indent: 4; indent-tabs-mode: nil -*-
3 * :indentSize=4:noTabs=true:tabSize=4:indentOnTab=true:indentOnEnter=true:mode=java:
4 * ex: set tabstop=4 expandtab:
5 *
6 * MrPostman - webmail <-> email gateway
7 * Copyright (C) 2002-2003 MrPostman Development Group
8 * Projectpage: http://mrbook.org/mrpostman/
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 * In particular, this implies that users are responsible for
21 * using MrPostman after reading the terms and conditions given
22 * by their web-mail provider.
23 *
24 * You should have received a copy of the GNU General Public License
25 * Named LICENSE in the base directory of this distribution,
26 * if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 package com.sonalb;
31
32 import java.text.ParsePosition;
33 import java.text.SimpleDateFormat;
34
35 import java.util.Comparator;
36 import java.util.Date;
37 import java.util.SimpleTimeZone;
38 import java.util.StringTokenizer;
39
40
41 /**
42
43 * Utility class containing several general-purpose methods for
44
45 * system-wide consumption.
46
47 *
48
49 * @author Sonal Bansal
50
51 */
52 public abstract class Utils {
53 public static final String CVSID = "$Id: Utils.java,v 1.5 2003/02/09 23:38:09 lbruand Exp $";
54
55 private Utils() {
56 }
57
58 /**
59
60 * Returns true if argument is either <code>null</code> or is full of
61
62 * whitespace. The argument is full of whitespace if after calling <code>String.trim()</code>
63
64 * on it, it equals(""). In other words, whitespace determination is done by
65
66 * <code>String.trim()</code>.
67
68 *
69
70 * @param s the String to be tested.
71
72 * @see java.lang.String#trim()
73
74 */
75 public static boolean isNullOrWhiteSpace(String s) {
76 if ((s == null) || "".equals(s.trim())) {
77 return (true);
78 }
79
80 return (false);
81 }
82
83 /**
84
85 * Returns the String obtained by removing any whitespace at both ends of the argument.
86
87 * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>. It is
88
89 * different from <code>String.trim()</code> which also removes any control characters.
90
91 *
92
93 * @param s the String to be trimmed.
94
95 * @return the trimmed String.
96
97 * @see java.lang.Character#isWhitespace(char)
98
99 * @see java.lang.String#trim()
100
101 */
102 public static String trimWhitespace(String s) {
103 if (s == null) {
104 return (s);
105 }
106
107 return (trimRightWS(trimLeftWS(s)));
108 }
109
110 /**
111
112 * Returns the String obtained by removing any whitespace at the left hand side of the argument.
113
114 * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>.
115
116 *
117
118 * @see java.lang.Character#isWhitespace(char)
119
120 * @param s the String to be trimmed.
121
122 * @return the trimmed String.
123
124 */
125 public static String trimLeftWS(String s) {
126 if (s == null) {
127 return (s);
128 }
129
130 for (int i = 0; i < s.length(); i++) {
131 if (!Character.isWhitespace(s.charAt(i))) {
132 return (s.substring(i));
133 }
134 }
135
136 return (s);
137 }
138
139 /**
140
141 * Returns the String obtained by removing any whitespace at the right hand side of the argument.
142
143 * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>.
144
145 *
146
147 * @see java.lang.Character#isWhitespace(char)
148
149 * @param s the String to be trimmed.
150
151 * @return the trimmed String.
152
153 */
154 public static String trimRightWS(String s) {
155 if (s == null) {
156 return (s);
157 }
158
159 for (int i = s.length() - 1; i >= 0; i--) {
160 if (!Character.isWhitespace(s.charAt(i))) {
161 return (s.substring(0, i + 1));
162 }
163 }
164
165 return (s);
166 }
167
168 /**
169
170 * Convenience synonym for <code>trimWhitespace(String)</code>.
171
172 *
173
174 * @see #trimWhitespace(String)
175
176 * @param s the String to be trimmed.
177
178 * @return the trimmed String.
179
180 */
181 public static String trimWS(String s) {
182 return (trimWhitespace(s));
183 }
184
185 /**
186
187 * Tokenizes the argument String into several constituent Strings, separated by commas,
188
189 * and returns the tokens as an array.
190
191 *
192
193 * @see #delimitedStringToArray(String, String)
194
195 * @param s the String to be tokenized.
196
197 * @return the array of token Strings.
198
199 */
200 public static String[] csvStringToArray(String s) {
201 return (delimitedStringToArray(s, ","));
202 }
203
204 /**
205
206 * Tokenizes the argument String into several constituent Strings, separated by specified
207
208 * delimiters, and returns the tokens as an array. Every character of the delimiter String is
209
210 * treated as a token-separator individually.
211
212 *
213
214 * @param s the String to be tokenized.
215
216 * @param delimiters the String of delimiters.
217
218 * @return the array of token Strings.
219
220 */
221 public static String[] delimitedStringToArray(String s, String delimiters) {
222 if (isNullOrWhiteSpace(s)) {
223 return (null);
224 }
225
226 delimiters = (delimiters == null) ? ",;" : delimiters;
227
228 StringTokenizer st = new StringTokenizer(s, delimiters);
229
230 int num;
231
232 if ((num = st.countTokens()) == 0) {
233 return (null);
234 }
235
236 String[] array = new String[num];
237
238 for (int i = 0; i < num; i++) {
239 array[i] = st.nextToken();
240 }
241
242 return (array);
243 }
244
245 /**
246
247 * Checks whether the specified Object exists in the given array. The <code>Object.equals(Object)</code>
248
249 * method is used to test for equality.
250
251 *
252
253 * @see java.lang.Object#equals(Object)
254
255 * @param obj the Object to be searched for.
256
257 * @param array the array which has to be searched.
258
259 * @return <code>true</code> if the Object exists in the array; <code>false</code> if the Object
260
261 * does not exist in the array, or the object, or the array is <code>null</code>.
262
263 */
264 public static boolean isInArray(Object obj, Object[] array) {
265 if ((obj == null) || (array == null)) {
266 return (false);
267 }
268
269 for (int i = 0; i < array.length; i++) {
270 if (array[i].equals(obj)) {
271 return (true);
272 }
273 }
274
275 return (false);
276 }
277
278 /**
279
280 * Counts the number of times the specified character appears in the input String. For example,
281
282 * <code>countInstances("abcabcdabcde",'a')</code> returns 3.
283
284 *
285
286 * @param s the String to be counted in.
287
288 * @param c the character to be counted.
289
290 * @return the number of occurrences of <code>c</code> in <code>s</code> ; -1 if <code>s</code> is <code>null</code>.
291
292 */
293 public static int countInstances(String s, char c) {
294 if (isNullOrWhiteSpace(s)) {
295 return (-1);
296 }
297
298 int count = 0;
299
300 for (int i = 0; i < s.length(); i++) {
301 if (s.charAt(i) == c) {
302 count++;
303 }
304 }
305
306 return (count);
307 }
308
309 /**
310
311 * Counts the number of times the specified String appears in the input String. For example,
312
313 * <code>countInstances("abcabcdabcde","cd")</code> returns 2.
314
315 *
316
317 * @param s the String to be counted in.
318
319 * @param c the String to be counted.
320
321 * @return the number of occurrences of <code>c</code> in <code>s</code> ; -1 if <code>s</code> or <code>c</code> is <code>null</code>.
322
323 */
324 public static int countInstances(String s, String c) {
325 if (isNullOrWhiteSpace(s) || isNullOrWhiteSpace(c)) {
326 return (-1);
327 }
328
329 int count = 0;
330
331 int len = c.length();
332
333 for (int i = 0; i < s.length(); i += len) {
334 if ((i = s.indexOf(c, i)) != -1) {
335 count++;
336 } else {
337 break;
338 }
339 }
340
341 return (count);
342 }
343
344 /**
345
346 * Checks whether the input String is a valid IP address (quad).
347
348 *
349
350 * @param s the String to be checked.
351
352 * @return <code>true</code> if the String IS an IP address ; <code>false</code> if
353
354 * it is not, or <code>s</code> is <code>null</code>.
355
356 * @see java.net.InetAddress
357
358 */
359 public static boolean isIPAddress(String s) {
360 if (isNullOrWhiteSpace(s) || (s.indexOf('.') == -1)) {
361 return (false);
362 }
363
364 s = s.trim();
365
366 int index;
367 int dotCount = 0;
368 int[] dotPos = new int[5];
369
370 char ch;
371
372 dotPos[0] = -1;
373
374 dotPos[4] = s.length();
375
376 for (index = 0; (index < s.length()) && (dotCount < 4); index++) {
377 ch = s.charAt(index);
378
379 if (!Character.isDigit(ch) && (ch != '.')) {
380 return (false);
381 } else if (ch == '.') {
382 dotPos[++dotCount] = index;
383 }
384 }
385
386 if (dotCount != 3) {
387 return (false);
388 }
389
390 try {
391 String num;
392
393 int number;
394
395 for (dotCount = 1; dotCount < 5; dotCount++) {
396 index = dotPos[dotCount - 1] + 1;
397
398 num = s.substring(index, dotPos[dotCount]);
399
400 number = Integer.valueOf(num).intValue();
401
402 if ((number < 0) || (number > 255)) {
403 return (false);
404 }
405 }
406 } catch (Exception e) {
407 return (false);
408 }
409
410 return (true);
411 }
412
413 /**
414
415 * Converts the input Date into a String formatted as specified by RFC 1123 of the IETF.
416
417 * The output String is in the format "Sun, 06 Nov 1994 08:49:37 GMT".
418
419 *
420
421 * @param d the Date to be converted.
422
423 * @return the String representation of the date as specified by RFC1123 ; <code>null</code>
424
425 * if input is <code>null</code>.
426
427 * @see java.util.Date
428
429 */
430 public static String convertToHttpDate(Date d) {
431 if (d == null) {
432 return (null);
433 }
434
435 SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
436
437 sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
438
439 return (sdf.format(d));
440 }
441
442 /**
443
444 * Parses the input date String into a Date object. The input date String is
445
446 * expected to be in one of the following formats (note the spaces) :-<p>
447
448 * <ul>
449
450 * <li>"Sun, 06 Nov 1994 08:49:37 GMT" ; RFC 822, updated by RFC 1123</li>
451
452 * <li>"Sunday, 06-Nov-94 08:49:37 GMT" ; RFC 850, obsoleted by RFC 1036</li>
453
454 * <li>"Sunday, 06-Nov-1994 08:49:37 GMT" ; RFC 1036</li>
455
456 * <li>"Sun Nov 6 08:49:37 1994" ; ANSI C's asctime() format</li>
457
458 * </ul>
459
460 *
461
462 * @param date the HTTP date String to be converted.
463
464 * @return the parsed Date object ; <code>null</code> if
465
466 * parsing was unsuccessful or input was <code>null</code>.
467
468 */
469 public static Date parseHttpDateStringToDate(String date) {
470 if (date == null) {
471 return (null);
472 }
473
474 StringTokenizer st = new StringTokenizer(date.trim(), " ");
475
476 int iNumTokens = st.countTokens();
477
478 String format = null;
479
480 if (iNumTokens == 5) // Its an asctime date ... wkday SP month SP ( 2DIGIT | ( SP 1DIGIT )) SP time SP 4DIGIT
481 { // ; month day (e.g., Jun 2)
482 // Sun Nov 6 08:49:37 1994
483 format = "EEE MMM dd HH:mm:ss yyyy";
484 } else if (iNumTokens == 4) // Its an RFC850 date ... weekday "," SP 2DIGIT "-" month "-" 2DIGIT SP time SP "GMT"
485 { // ; day-month-year (e.g., 02-Jun-82)
486 String dtok = null; // may have 2 or 4-digit year
487
488 st.nextToken();
489
490 dtok = st.nextToken().trim();
491
492 if (dtok.length() == 9) { // has 2-digit year
493 // Sunday, 06-Nov-94 08:49:37 GMT
494 format = "EEEE, dd-MMM-yy HH:mm:ss zzz";
495 } else if (dtok.length() == 11) { // has 4-digit year
496 // Sunday, 06-Nov-1994 08:49:37 GMT
497 format = "EEEE, dd-MMM-yyyy HH:mm:ss zzz";
498 } else {
499 return (null);
500 }
501 } else if (iNumTokens == 6) // Its an RFC1123 date ... wkday "," SP 2DIGIT SP month SP 4DIGIT SP time SP "GMT"
502 { // ; day-month-year (e.g., 02 Jun 1982)
503 //Sun, 06 Nov 1994 08:49:37 GMT
504 format = "EEE, dd MMM yyyy HH:mm:ss zzz";
505 } else {
506 return (null);
507 }
508
509 SimpleDateFormat sdf = new SimpleDateFormat(format);
510
511 sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
512
513 Date d = sdf.parse(date, new ParsePosition(0));
514
515 return (d);
516 }
517
518 /**
519
520 * Returns true if argument is either <code>null</code> or it equals("").
521
522 * It does not trim the input, unlike <code>isNullOrWhiteSpace(String)</code>.
523
524 *
525
526 * @param s the String to be tested.
527
528 * @see #isNullOrWhiteSpace(String)
529
530 */
531 public static boolean isEmpty(String s) {
532 return ((s == null) || s.equals(""));
533 }
534
535 /**
536
537 * Replaces all occurrences of a String in the input String with another String.
538
539 *
540
541 * @param source the String in which the replacements are to be carried out.
542
543 * @param find the String which must be searched for.
544
545 * @param replace the String which replaces the search String.
546
547 * @param bIgnoreCase determines whether case-sensitive search is done.
548
549 * @return the processed String if any replacements were made ; the original String if
550
551 * search String was not found or search String is empty.
552
553 * @throws IllegalArgumentException Thrown if source String is empty.
554
555 */
556 public static String replaceAll(String source, String find, String replace, boolean bIgnoreCase)
557 throws IllegalArgumentException {
558 if (isEmpty(source)) {
559 throw new IllegalArgumentException("Empty source String");
560 } else if (isEmpty(find)) {
561 return (source);
562 }
563
564 if (replace == null) {
565 replace = "";
566 }
567
568 StringBuffer sb = new StringBuffer(source);
569
570 StringBuffer mod;
571
572 boolean bDone = false;
573
574 int prevIndex = 0;
575 int currIndex = 0;
576 int i = 0;
577
578 if (bIgnoreCase) {
579 source = source.toLowerCase();
580
581 find = find.toLowerCase();
582 }
583
584 mod = new StringBuffer(source);
585
586 while (!bDone) {
587 if ((currIndex = mod.toString().indexOf(find, prevIndex)) != -1) {
588 sb = sb.replace(currIndex, currIndex + find.length(), replace);
589
590 mod = mod.replace(currIndex, currIndex + find.length(), replace);
591
592 prevIndex = currIndex + replace.length();
593 } else {
594 bDone = true;
595 }
596 }
597
598 return (sb.toString());
599 }
600
601 /**
602
603 * Determines whether every double-quote has its closing partner in the input String.
604
605 *
606
607 * @param s the String to be tested.
608
609 * @return <code>true</code> if quotes match or no quotes exist ; <code>false</code> otherwise.
610
611 */
612 public static boolean matchQuotes(String s) {
613 int numQuotes = 0;
614 int numEscapedQuotes = 0;
615
616 numQuotes = countInstances(s, '\"');
617
618 numEscapedQuotes = countInstances(s, "\\\"");
619
620 if (numQuotes == -1) {
621 return (true);
622 }
623
624 if (numEscapedQuotes == -1) {
625 numEscapedQuotes = 0;
626 }
627
628 return (((numQuotes - numEscapedQuotes) % 2) == 0);
629 }
630
631 /**
632
633 * Removes the outermost double-quotes pair from the input String. Trims the input String
634
635 * before processing.
636
637 *
638
639 * @param s the String to be stripped.
640
641 * @return the stripped String ; the original String if it is not quoted or quotes don't match.
642
643 */
644 public static String stripQuotes(String s) {
645 if (isNullOrWhiteSpace(s) || !matchQuotes(s)) {
646 return (s);
647 }
648
649 String s2 = trimWhitespace(s);
650
651 if (isQuoted(s2)) {
652 return (s2.substring(1, s2.length() - 1));
653 }
654
655 return (s);
656 }
657
658 /**
659
660 * Determines whether the input String is enclosed in double-quotes. Trims the input String
661
662 * first.
663
664 *
665
666 * @param s the String to be tested.
667
668 * @return <code>true</code> if input String is quoted ;
669
670 * <code>false</code> if it isn't or it is empty.
671
672 * @see #trimWhitespace(String)
673
674 */
675 public static boolean isQuoted(String s) {
676 if (isNullOrWhiteSpace(s) || !matchQuotes(s)) {
677 return (false);
678 }
679
680 String s2 = trimWhitespace(s);
681
682 return ((s2.charAt(0) == '\"') && (s.charAt(s2.length() - 1) == '\"'));
683 }
684
685 /**
686
687 * Converts the input integer into a more readable comma-separated String. A
688
689 * comma is inserted after every three digits, starting from the unit's place. For
690
691 * example, <p><pre>
692
693 * 12345 is converted to 12,345
694
695 * 987654321 is converted to 987,654,321</pre>
696
697 *
698
699 * @param i the integer to be converted.
700
701 * @return the String representation of the formatted integer ; if the input
702
703 * lies between -1000 & 1000 (not inclusive) , the returned String is
704
705 * the same as <code>String.valueOf(int)</code>
706
707 * @see java.lang.String#valueOf(int)
708
709 */
710 public static String commaFormatInteger(int i) {
711 boolean bNegative = (i < 0);
712
713 if ((i == 0) || ((i > 0) && (i < 1000)) || ((i < 0) && (i > -1000))) {
714 return (String.valueOf(i));
715 }
716
717 i = Math.abs(i);
718
719 StringBuffer sb = new StringBuffer(String.valueOf(i));
720
721 sb.reverse();
722
723 int l = sb.length();
724
725 int iter = l / 3;
726
727 if ((l % 3) == 0) {
728 iter--;
729 }
730
731 for (int c = 1; c <= iter; c++) {
732 l = 3 * c;
733
734 sb.insert((l + c) - 1, ',');
735 }
736
737 if (bNegative) {
738 sb.append('-');
739 }
740
741 return (sb.reverse().toString());
742 }
743
744 /**
745
746 * Returns the number which would be in the n<sup>th</sup> place if the input array were sorted
747
748 * in descending order. For arrays with distinct elements, this returns the n<sup>th</sup> largest
749
750 * number. For example, in the array {1,2,3,4,5,6}, <code>findOrderedMax(list, 3)</code> would return 4.
751
752 * However, the result is quite different in arrays with repeated elements.
753
754 * For example, in the array {1,2,6,2}, both <code>findOrderedMax(list,2)</code>
755
756 * and <code>findOrderedMax(list,3)</code> return 2.
757
758 *
759
760 * @see #findMax(int[],int)
761
762 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
763
764 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
765
766 * Or, when the order <code>n</code> is less than or equal to 0.
767
768 * @param inputlist the array of numbers.
769
770 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
771
772 */
773 public static int findOrderedMax(int[] inputlist, int n) {
774 if (inputlist.length < n) {
775 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
776 }
777
778 if (n <= 0) {
779 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
780 }
781
782 int numIters;
783 int i;
784
785 int maxIndex;
786 int temp;
787
788 int[] list = new int[inputlist.length];
789
790 System.arraycopy(inputlist, 0, list, 0, list.length);
791
792 for (numIters = 0; numIters < n; numIters++) {
793 maxIndex = 0;
794
795 for (i = 0; i < (list.length - numIters); i++) {
796 if (list[i] > list[maxIndex]) {
797 maxIndex = i;
798 }
799 }
800
801 temp = list[i - 1];
802
803 list[i - 1] = list[maxIndex];
804
805 list[maxIndex] = temp;
806 }
807
808 return (list[list.length - n]);
809 }
810
811 /**
812
813 * Returns the n<sup>th</sup> largest number in the input array. This method disregards
814
815 * duplicate elements unlike the <code>findOrderedMax</code> method. For example, in the array {1,2,3,4,5,6},
816
817 * <code>findMax(list, 3)</code> would return 4. In the array {1,2,6,2}, <code>findMax(list,2)</code> would return 2, and
818
819 * and <code>findMax(list,3)</code> would return 1. <p> Note that in an array with repeating elements, it is possible that
820
821 * the required order may not exist. For example, in the array {1,2,2}, <code>findMax(list,3)</code>, there is no third-largest
822
823 * number. In such cases, this method returns the number with highest order less than or equal to <code>n</code>. In other words,
824
825 * in the above example, this method would return 1, which is the same value as would be returned by <code>findMax(list,2)</code>.
826
827 *
828
829 * @see #findOrderedMax(int[],int)
830
831 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
832
833 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
834
835 * Or, when the order <code>n</code> is less than or equal to 0.
836
837 * @param inputlist the array of numbers.
838
839 * @param n the desired order. For example, 1 indicates largest number; 2 indicates second-largest number, and so on.
840
841 */
842 public static int findMax(int[] inputlist, int n) {
843 if (inputlist.length < n) {
844 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
845 }
846
847 if (n <= 0) {
848 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
849 }
850
851 int numIters;
852 int i;
853
854 int maxIndex;
855 int temp;
856
857 int[] order = new int[n];
858
859 int oindex = 0;
860
861 int currIter = 0;
862
863 int[] list = new int[inputlist.length];
864
865 System.arraycopy(inputlist, 0, list, 0, list.length);
866
867 for (numIters = 0; numIters < list.length; numIters++) {
868 maxIndex = 0;
869
870 for (i = 0; i < (list.length - numIters); i++) {
871 if (list[i] > list[maxIndex]) {
872 maxIndex = i;
873 }
874 }
875
876 temp = list[maxIndex];
877
878 list[maxIndex] = list[i - 1];
879
880 list[i - 1] = temp;
881
882 if ((oindex == 0) || (order[oindex - 1] != temp)) {
883 order[oindex++] = temp;
884
885 currIter++;
886 }
887
888 if (currIter == n) {
889 break;
890 }
891 }
892
893 return (order[oindex - 1]);
894 }
895
896 /**
897
898 * Returns the number which would be in the n<sup>th</sup> place if the input array were sorted
899
900 * in ascending order. For arrays with distinct elements, this returns the n<sup>th</sup> smallest
901
902 * number. For example, in the array {1,2,3,4,5,6}, <code>findOrderedMin(list, 3)</code> would return 3.
903
904 * However, the result is quite different in arrays with repeated elements.
905
906 * For example, in the array {1,2,6,2}, both <code>findOrderedMin(list,2)</code>
907
908 * and <code>findOrderedMin(list,3)</code> return 2.
909
910 *
911
912 * @see #findMin(int[],int)
913
914 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
915
916 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
917
918 * Or, when the order <code>n</code> is less than or equal to 0.
919
920 * @param inputlist the array of numbers.
921
922 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
923
924 */
925 public static int findOrderedMin(int[] inputlist, int n) {
926 if (inputlist.length < n) {
927 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
928 }
929
930 if (n <= 0) {
931 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
932 }
933
934 int numIters;
935 int i;
936
937 int minIndex;
938 int temp;
939
940 int[] list = new int[inputlist.length];
941
942 System.arraycopy(inputlist, 0, list, 0, list.length);
943
944 for (numIters = 0; numIters < n; numIters++) {
945 minIndex = 0;
946
947 for (i = 0; i < (list.length - numIters); i++) {
948 if (list[i] < list[minIndex]) {
949 minIndex = i;
950 }
951 }
952
953 temp = list[i - 1];
954
955 list[i - 1] = list[minIndex];
956
957 list[minIndex] = temp;
958 }
959
960 return (list[list.length - n]);
961 }
962
963 /**
964
965 * Returns the n<sup>th</sup> smallest number in the input array. This method disregards
966
967 * duplicate elements unlike the <code>findOrderedMin</code> method. For example, in the array {1,2,3,4,5,6},
968
969 * <code>findMin(list, 3)</code> would return 3. In the array {1,2,6,2}, <code>findMin(list,2)</code> would return 2, and
970
971 * and <code>findMin(list,3)</code> would return 6. <p> Note that in an array with repeating elements, it is possible that
972
973 * the required order may not exist. For example, in the array {1,2,2}, <code>findMin(list,3)</code>, there is no third-smallest
974
975 * number. In such cases, this method returns the number with highest order less than or equal to <code>n</code>. In other words,
976
977 * in the above example, this method would return 2, which is the same value as would be returned by <code>findMax(list,2)</code>.
978
979 *
980
981 * @see #findOrderedMin(int[],int)
982
983 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
984
985 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
986
987 * Or, when the order <code>n</code> is less than or equal to 0.
988
989 * @param inputlist the array of numbers.
990
991 * @param n the desired order. For example, 1 indicates smallest number; 2 indicates second-smallest number, and so on.
992
993 */
994 public static int findMin(int[] inputlist, int n) {
995 if (inputlist.length < n) {
996 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
997 }
998
999 if (n <= 0) {
1000 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1001 }
1002
1003 int numIters;
1004 int i;
1005
1006 int minIndex;
1007 int temp;
1008
1009 int[] order = new int[n];
1010
1011 int oindex = 0;
1012
1013 int currIter = 0;
1014
1015 int[] list = new int[inputlist.length];
1016
1017 System.arraycopy(inputlist, 0, list, 0, list.length);
1018
1019 for (numIters = 0; numIters < list.length; numIters++) {
1020 minIndex = 0;
1021
1022 for (i = 0; i < (list.length - numIters); i++) {
1023 if (list[i] < list[minIndex]) {
1024 minIndex = i;
1025 }
1026 }
1027
1028 temp = list[minIndex];
1029
1030 list[minIndex] = list[i - 1];
1031
1032 list[i - 1] = temp;
1033
1034 if ((oindex == 0) || (order[oindex - 1] != temp)) {
1035 order[oindex++] = temp;
1036
1037 currIter++;
1038 }
1039
1040 if (currIter == n) {
1041 break;
1042 }
1043 }
1044
1045 return (order[oindex - 1]);
1046 }
1047
1048 /**
1049
1050 * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1051
1052 * in descending order. This method allows comparison of <code>Object</code>s. It follows similar
1053
1054 * semantics as the <code>findOrderedMax(int[], int)</code> method.
1055
1056 *
1057
1058 * @see #findMax(Comparable[],int)
1059
1060 * @see #findOrderedMax(int[],int)
1061
1062 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1063
1064 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1065
1066 * Or, when the order <code>n</code> is less than or equal to 0.
1067
1068 * @param inputlist the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1069
1070 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1071
1072 */
1073 public static Object findOrderedMax(Comparable[] inputlist, int n) {
1074 if (inputlist.length < n) {
1075 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1076 }
1077
1078 if (n <= 0) {
1079 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1080 }
1081
1082 int numIters;
1083 int i;
1084
1085 int maxIndex;
1086
1087 Comparable temp;
1088
1089 Comparable[] list = new Comparable[inputlist.length];
1090
1091 System.arraycopy(inputlist, 0, list, 0, list.length);
1092
1093 for (numIters = 0; numIters < n; numIters++) {
1094 maxIndex = 0;
1095
1096 for (i = 0; i < (list.length - numIters); i++) {
1097 if (list[i].compareTo(list[maxIndex]) > 0) {
1098 maxIndex = i;
1099 }
1100 }
1101
1102 temp = list[i - 1];
1103
1104 list[i - 1] = list[maxIndex];
1105
1106 list[maxIndex] = temp;
1107 }
1108
1109 return (list[list.length - n]);
1110 }
1111
1112 /**
1113
1114 * Returns the n<sup>th</sup> largest object in the input array. This method allows comparison of <code>Object</code>s. It follows similar
1115
1116 * semantics as the <code>findMax(int[], int)</code> method.
1117
1118 *
1119
1120 * @see #findOrderedMax(Comparable[],int)
1121
1122 * @see #findMax(int[],int)
1123
1124 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1125
1126 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1127
1128 * Or, when the order <code>n</code> is less than or equal to 0.
1129
1130 * @param inputlist the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1131
1132 * @param n the desired order. For example, 1 indicates largest object; 2 indicates second-largest object, and so on.
1133
1134 */
1135 public static Object findMax(Comparable[] inputlist, int n) {
1136 if (inputlist.length < n) {
1137 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1138 }
1139
1140 if (n <= 0) {
1141 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1142 }
1143
1144 int numIters;
1145 int i;
1146
1147 int maxIndex;
1148
1149 Comparable temp;
1150
1151 Comparable[] order = new Comparable[n];
1152
1153 int oindex = 0;
1154
1155 int currIter = 0;
1156
1157 Comparable[] list = new Comparable[inputlist.length];
1158
1159 System.arraycopy(inputlist, 0, list, 0, list.length);
1160
1161 for (numIters = 0; numIters < list.length; numIters++) {
1162 maxIndex = 0;
1163
1164 for (i = 0; i < (list.length - numIters); i++) {
1165 if (list[i].compareTo(list[maxIndex]) > 0) {
1166 maxIndex = i;
1167 }
1168 }
1169
1170 temp = list[maxIndex];
1171
1172 list[maxIndex] = list[i - 1];
1173
1174 list[i - 1] = temp;
1175
1176 if ((oindex == 0) || !order[oindex - 1].equals(temp)) {
1177 order[oindex++] = temp;
1178
1179 currIter++;
1180 }
1181
1182 if (currIter == n) {
1183 break;
1184 }
1185 }
1186
1187 return (order[oindex - 1]);
1188 }
1189
1190 /**
1191
1192 * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1193
1194 * in ascending order. This method allows comparison of <code>Object</code>s. It follows similar
1195
1196 * semantics as the <code>findOrderedMin(int[], int)</code> method.
1197
1198 *
1199
1200 * @see #findMin(Comparable[],int)
1201
1202 * @see #findOrderedMin(int[],int)
1203
1204 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1205
1206 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1207
1208 * Or, when the order <code>n</code> is less than or equal to 0.
1209
1210 * @param inputlist the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1211
1212 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1213
1214 */
1215 public static Object findOrderedMin(Comparable[] inputlist, int n) {
1216 if (inputlist.length < n) {
1217 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1218 }
1219
1220 if (n <= 0) {
1221 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1222 }
1223
1224 int numIters;
1225 int i;
1226
1227 int minIndex;
1228
1229 Comparable temp;
1230
1231 Comparable[] list = new Comparable[inputlist.length];
1232
1233 System.arraycopy(inputlist, 0, list, 0, list.length);
1234
1235 for (numIters = 0; numIters < n; numIters++) {
1236 minIndex = 0;
1237
1238 for (i = 0; i < (list.length - numIters); i++) {
1239 if (list[i].compareTo(list[minIndex]) < 0) {
1240 minIndex = i;
1241 }
1242 }
1243
1244 temp = list[i - 1];
1245
1246 list[i - 1] = list[minIndex];
1247
1248 list[minIndex] = temp;
1249 }
1250
1251 return (list[list.length - n]);
1252 }
1253
1254 /**
1255
1256 * Returns the n<sup>th</sup> smallest object in the input array. This method allows comparison of <code>Object</code>s. It follows similar
1257
1258 * semantics as the <code>findMin(int[], int)</code> method.
1259
1260 *
1261
1262 * @see #findOrderedMin(Comparable[],int)
1263
1264 * @see #findMin(int[],int)
1265
1266 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1267
1268 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1269
1270 * Or, when the order <code>n</code> is less than or equal to 0.
1271
1272 * @param inputlist the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1273
1274 * @param n the desired order. For example, 1 indicates smallest object; 2 indicates second-smallest object, and so on.
1275
1276 */
1277 public static Object findMin(Comparable[] inputlist, int n) {
1278 if (inputlist.length < n) {
1279 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1280 }
1281
1282 if (n <= 0) {
1283 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1284 }
1285
1286 int numIters;
1287 int i;
1288
1289 int minIndex;
1290
1291 Comparable temp;
1292
1293 Comparable[] order = new Comparable[n];
1294
1295 int oindex = 0;
1296
1297 int currIter = 0;
1298
1299 Comparable[] list = new Comparable[inputlist.length];
1300
1301 System.arraycopy(inputlist, 0, list, 0, list.length);
1302
1303 for (numIters = 0; numIters < list.length; numIters++) {
1304 minIndex = 0;
1305
1306 for (i = 0; i < (list.length - numIters); i++) {
1307 if (list[i].compareTo(list[minIndex]) < 0) {
1308 minIndex = i;
1309 }
1310 }
1311
1312 temp = list[minIndex];
1313
1314 list[minIndex] = list[i - 1];
1315
1316 list[i - 1] = temp;
1317
1318 if ((oindex == 0) || !order[oindex - 1].equals(temp)) {
1319 order[oindex++] = temp;
1320
1321 currIter++;
1322 }
1323
1324 if (currIter == n) {
1325 break;
1326 }
1327 }
1328
1329 return (order[oindex - 1]);
1330 }
1331
1332 /**
1333
1334 * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1335
1336 * in descending order. This method allows comparison of <code>Object</code>s. The comparison logic
1337
1338 * is provided by the <code>Comparator</code> argument. It follows similar
1339
1340 * semantics as the <code>findOrderedMax(int[], int)</code> method.
1341
1342 *
1343
1344 * @see #findMax(Object[],int,Comparator)
1345
1346 * @see #findOrderedMax(int[],int)
1347
1348 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1349
1350 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1351
1352 * Or, when the order <code>n</code> is less than or equal to 0.
1353
1354 * @param c the <code>Comparator</code> that provides the ordering logic.
1355
1356 * @param inputlist the array of <code>Object</code>s.
1357
1358 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1359
1360 */
1361 public static Object findOrderedMax(Object[] inputlist, int n, Comparator c) {
1362 if (inputlist.length < n) {
1363 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1364 }
1365
1366 if (n <= 0) {
1367 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1368 }
1369
1370 int numIters;
1371 int i;
1372
1373 int maxIndex;
1374
1375 Object temp;
1376
1377 Object[] list = new Object[inputlist.length];
1378
1379 System.arraycopy(inputlist, 0, list, 0, list.length);
1380
1381 for (numIters = 0; numIters < n; numIters++) {
1382 maxIndex = 0;
1383
1384 for (i = 0; i < (list.length - numIters); i++) {
1385 if (c.compare(list[i], list[maxIndex]) > 0) {
1386 maxIndex = i;
1387 }
1388 }
1389
1390 temp = list[i - 1];
1391
1392 list[i - 1] = list[maxIndex];
1393
1394 list[maxIndex] = temp;
1395 }
1396
1397 return (list[list.length - n]);
1398 }
1399
1400 /**
1401
1402 * Returns the n<sup>th</sup> largest object in the input array. This method allows comparison of <code>Object</code>s.
1403
1404 * The comparison logic is provided by the <code>Comparator</code> argument. It follows similar
1405
1406 * semantics as the <code>findMax(int[], int)</code> method.
1407
1408 *
1409
1410 * @see #findOrderedMax(Object[],int,Comparator)
1411
1412 * @see #findMax(int[],int)
1413
1414 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1415
1416 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1417
1418 * Or, when the order <code>n</code> is less than or equal to 0.
1419
1420 * @param c the <code>Comparator</code> that provides the ordering logic.
1421
1422 * @param inputlist the array of <code>Object</code>s.
1423
1424 * @param n the desired order. For example, 1 indicates largest object; 2 indicates second-largest object, and so on.
1425
1426 */
1427 public static Object findMax(Object[] inputlist, int n, Comparator c) {
1428 if (inputlist.length < n) {
1429 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1430 }
1431
1432 if (n <= 0) {
1433 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1434 }
1435
1436 int numIters;
1437 int i;
1438
1439 int maxIndex;
1440
1441 Object temp;
1442
1443 Object[] order = new Object[n];
1444
1445 int oindex = 0;
1446
1447 int currIter = 0;
1448
1449 Object[] list = new Object[inputlist.length];
1450
1451 System.arraycopy(inputlist, 0, list, 0, list.length);
1452
1453 for (numIters = 0; numIters < list.length; numIters++) {
1454 maxIndex = 0;
1455
1456 for (i = 0; i < (list.length - numIters); i++) {
1457 if (c.compare(list[i], list[maxIndex]) > 0) {
1458 maxIndex = i;
1459 }
1460 }
1461
1462 temp = list[maxIndex];
1463
1464 list[maxIndex] = list[i - 1];
1465
1466 list[i - 1] = temp;
1467
1468 if ((oindex == 0) || !(c.compare(order[oindex - 1], temp) == 0)) {
1469 order[oindex++] = temp;
1470
1471 currIter++;
1472 }
1473
1474 if (currIter == n) {
1475 break;
1476 }
1477 }
1478
1479 return (order[oindex - 1]);
1480 }
1481
1482 /**
1483
1484 * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1485
1486 * in ascending order. This method allows comparison of <code>Object</code>s. The comparison logic
1487
1488 * is provided by the <code>Comparator</code> argument. It follows similar
1489
1490 * semantics as the <code>findOrderedMin(int[], int)</code> method.
1491
1492 *
1493
1494 * @see #findMin(Object[],int,Comparator)
1495
1496 * @see #findOrderedMin(int[],int)
1497
1498 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1499
1500 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1501
1502 * Or, when the order <code>n</code> is less than or equal to 0.
1503
1504 * @param c the <code>Comparator</code> that provides the ordering logic.
1505
1506 * @param inputlist the array of <code>Object</code>s.
1507
1508 * @param n the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1509
1510 */
1511 public static Object findOrderedMin(Object[] inputlist, int n, Comparator c) {
1512 if (inputlist.length < n) {
1513 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1514 }
1515
1516 if (n <= 0) {
1517 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1518 }
1519
1520 int numIters;
1521 int i;
1522
1523 int minIndex;
1524
1525 Object temp;
1526
1527 Object[] list = new Object[inputlist.length];
1528
1529 System.arraycopy(inputlist, 0, list, 0, list.length);
1530
1531 for (numIters = 0; numIters < n; numIters++) {
1532 minIndex = 0;
1533
1534 for (i = 0; i < (list.length - numIters); i++) {
1535 if (c.compare(list[i], list[minIndex]) < 0) {
1536 minIndex = i;
1537 }
1538 }
1539
1540 temp = list[i - 1];
1541
1542 list[i - 1] = list[minIndex];
1543
1544 list[minIndex] = temp;
1545 }
1546
1547 return (list[list.length - n]);
1548 }
1549
1550 /**
1551
1552 * Returns the n<sup>th</sup> smallest object in the input array. This method allows comparison of <code>Object</code>s.
1553
1554 * The comparison logic is provided by the <code>Comparator</code> argument. It follows similar
1555
1556 * semantics as the <code>findMin(int[], int)</code> method.
1557
1558 *
1559
1560 * @see #findOrderedMin(Object[],int,Comparator)
1561
1562 * @see #findMin(int[],int)
1563
1564 * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1565
1566 * the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1567
1568 * Or, when the order <code>n</code> is less than or equal to 0.
1569
1570 * @param c the <code>Comparator</code> that provides the ordering logic.
1571
1572 * @param inputlist the array of <code>Objects</code>.
1573
1574 * @param n the desired order. For example, 1 indicates smallest object; 2 indicates second-smallest object, and so on.
1575
1576 */
1577 public static Object findMin(Object[] inputlist, int n, Comparator c) {
1578 if (inputlist.length < n) {
1579 throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1580 }
1581
1582 if (n <= 0) {
1583 throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1584 }
1585
1586 int numIters;
1587 int i;
1588
1589 int minIndex;
1590
1591 Object temp;
1592
1593 Object[] order = new Object[n];
1594
1595 int oindex = 0;
1596
1597 int currIter = 0;
1598
1599 Object[] list = new Object[inputlist.length];
1600
1601 System.arraycopy(inputlist, 0, list, 0, list.length);
1602
1603 for (numIters = 0; numIters < list.length; numIters++) {
1604 minIndex = 0;
1605
1606 for (i = 0; i < (list.length - numIters); i++) {
1607 if (c.compare(list[i], list[minIndex]) < 0) {
1608 minIndex = i;
1609 }
1610 }
1611
1612 temp = list[minIndex];
1613
1614 list[minIndex] = list[i - 1];
1615
1616 list[i - 1] = temp;
1617
1618 if ((oindex == 0) || !(c.compare(order[oindex - 1], temp) == 0)) {
1619 order[oindex++] = temp;
1620
1621 currIter++;
1622 }
1623
1624 if (currIter == n) {
1625 break;
1626 }
1627 }
1628
1629 return (order[oindex - 1]);
1630 }
1631}