1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
|
/*
* Copyright (C) 2014-2021 Brian L. Browning
*
* This file is part of Beagle
*
* Beagle is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Beagle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package blbutil;
import java.io.File;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
/**
* Class {@code Utilities} contains miscellaneous static utility methods.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public class Utilities {
private Utilities() {
// private constructor to prevent instantiation
}
/**
* Returns a string representation of the command line arguments.
* The exact details of the representation are unspecified and
* subject to change.
*
* @param program the name of the program's jar file.
* @param args command line arguments.
* @return a string representation of the command line arguments.
*/
public static String commandLine(String program, String[] args) {
StringBuilder sb = new StringBuilder(args.length*20);
long maxMemory = Runtime.getRuntime().maxMemory();
sb.append(Const.nl);
sb.append("Command line: java");
if (maxMemory!=Long.MAX_VALUE) {
long maxMb = maxMemory / (1024*1024);
sb.append(" -Xmx");
sb.append(maxMb);
sb.append("m");
}
sb.append(" -jar ");
sb.append(program);
sb.append(Const.nl);
for (int j = 0; j < args.length; ++j) {
sb.append(" ");
sb.append(args[j]);
sb.append(Const.nl);
}
return sb.toString();
}
/**
* Prints a summary of memory use at the time of method invocation
* to standard output.
* @param msg a string a message to be printed with the summary
* of memory use
*/
public static void printMemoryUse(String msg) {
long Mb = 1024*1024;
Runtime rt = Runtime.getRuntime();
System.out.println(Const.nl + msg
+ Const.tab + "maxMb=" + (rt.maxMemory()/Mb)
+ Const.tab + "totalMb=" + (rt.totalMemory()/Mb)
+ Const.tab + "freeMb=" + (rt.freeMemory()/Mb)
+ Const.tab + "usedMb=" + ((rt.totalMemory() - rt.freeMemory())/Mb));
}
/**
* Returns the current local time as a string. The
* exact details of the string representation
* are unspecified and subject to change.
*
* @return the current local time as a string.
*/
public static String timeStamp() {
Date now = new Date();
SimpleDateFormat sdf =
new SimpleDateFormat("hh:mm a z 'on' dd MMM yyyy");
return sdf.format(now);
}
/**
* Returns the current minutes and seconds as a string. The
* exact details of the string representation
* are unspecified and subject to change.
*
* @return the current local time as a string.
*/
public static String minutesAndSeconds() {
Date now = new Date();
SimpleDateFormat sdf =
new SimpleDateFormat("mm:ss");
return sdf.format(now);
}
/**
* <p>Returns a set of identifiers found in a text file that has
* one identifier per line. The empty set is returned if
* {@code file == null}. Blank lines are ignored, and white-space that
* begins or ends a line is ignored.
* </p>
* If an {@code IOException} is thrown, an error message is printed
* to standard error and the Java virtual machine is forced to terminate.
*
* @param file a text file with one identifier per line
* @return a set of identifiers
*
* @throws IllegalArgumentException if the specified file does not exist
* @throws IllegalArgumentException if the specified file is a directory
* @throws IllegalArgumentException if any line of the specified
* file contains two non-white-space characters separated by one or
* more white-space characters
*/
public static Set<String> idSet(File file) {
if (file==null) {
return Collections.emptySet();
}
else {
if (file.exists()==false) {
String s = "file does not exist: " + file;
throw new IllegalArgumentException(s);
}
if (file.isDirectory()) {
String s = "file is a directory: " + file;
throw new IllegalArgumentException(s);
}
Set<String> idSet = new HashSet<>();
try (FileIt<String> it = InputIt.fromGzipFile(file)) {
while (it.hasNext()) {
String line = it.next().trim();
if (line.length() > 0) {
if (StringUtil.countFields(line) > 1) {
String s = "Line has more than one white-space delimited field (file: '"
+ file + "'; line: '" + line + "')";
throw new IllegalArgumentException(s);
}
idSet.add(line);
}
}
}
return idSet;
}
}
/**
* Prints the specified string to the specified {@code PrintWriter} and
* to standard out. The line separator string is not appended to the
* specified string before printing.
*
* @param out a print writer
* @param s a string to be printed
*
* @throws NullPointerException if {@code out == null}
*/
public static void duoPrint(PrintWriter out, CharSequence s) {
System.out.print(s);
out.print(s);
}
/**
* Prints the specified string to the specified {@code PrintWriter} and
* to standard out. The line separator string is appended to the
* specified string before printing.
*
* @param out a print writer
* @param s a string to be printed
*
* @throws NullPointerException if {@code out == null}
*/
public static void duoPrintln(PrintWriter out, CharSequence s) {
System.out.println(s);
out.println(s);
}
/**
* Returns a string representation of the specified elapsed time
* in the format "H hours M minutes S seconds".
*
* @param nanoseconds the elapsed time in nanoseconds
*
* @return a string representation of the specified elapsed time
*/
public static String elapsedNanos(long nanoseconds) {
long seconds = Math.round(nanoseconds /1000000000.0);
StringBuilder sb = new StringBuilder(80);
if (seconds >= 3600) {
long hours = seconds / 3600;
sb.append(hours);
sb.append(hours==1 ? " hour " : " hours ");
seconds %= 3600;
}
if (seconds >= 60) {
long minutes = seconds / 60;
sb.append(minutes);
sb.append(minutes==1 ? " minute " : " minutes ");
seconds %= 60;
}
sb.append(seconds);
sb.append(seconds==1 ? " second" : " seconds");
return sb.toString();
}
/**
* Prints the specified exception, its stack trace, and
* the specified string to standard error and then terminates the
* Java virtual machine.
*
* @param str a string to be printed to standard error
* @param thr an exception or error to be printed to standard error
*
* @throws NullPointerException if {@code t == null}
*/
public static void exit(Throwable thr, String str) {
System.err.println();
System.err.println(str);
System.err.println();
thr.printStackTrace(System.err);
exit();
}
/**
* Prints the specified exception, its stack trace and then terminates the
* Java virtual machine.
*
* @param t an exception or error to be printed to standard error
*
* @throws NullPointerException if {@code e == null}
*/
public static void exit(Throwable t) {
t.printStackTrace(System.err);
exit();
}
/**
* Prints the specified string to standard error and then terminates the
* Java virtual machine.
*
* @param s a string to be written to standard error
*/
public static void exit(String s) {
System.err.println();
System.err.println(s);
exit();
}
/**
* Prints "Terminating program." to standard error and terminates
* the Java virtual machine.
*/
public static void exit() {
System.err.println();
System.err.println("Terminating program.");
System.err.flush();
System.exit(1);
}
/**
* Randomly shuffles the elements of the specified array.
* @param ia an array to be shuffled
* @param random a random number generator
* @throws NullPointerException if {@code ia == null || random == null}
*/
public static void shuffle(int[] ia, Random random) {
for (int j=0; j<ia.length; ++j) {
int x = random.nextInt(ia.length-j);
int tmp = ia[j];
ia[j] = ia[j+x];
ia[j+x] = tmp;
}
}
/**
* Shuffles the specified array so that a random set of ${code nElements}
* elements from the array are the first ${code nElements} elements.
* The specified array is unchanged if {@code nElements <= 0}.
* @param ia an array to be shuffled
* @param nElements the size of the random set of elements which
* are shuffled to the beginning of the array
* @param random a random number generator
* @throws IndexOutOfBoundsException if {@code nElements > ia.length}
* @throws NullPointerException if {@code ia == null || random == null}
*/
public static void shuffle(int[] ia, int nElements, Random random) {
for (int j=0; j<nElements; ++j) {
int x = random.nextInt(ia.length-j);
int tmp = ia[j];
ia[j] = ia[j+x];
ia[j+x] = tmp;
}
}
/**
* Returns a two-dimensional array with indices of common array
* elements. If there are {@code n} elements in common between
* the {@code a1} and {@code a2} arrays, then for {@code j} satisfying
* {@code (0 <= j && j < n)}, the {@code [0][j]} and {@code P[1][j]}
* elements of the returned array are the indices of the {@code j}-th
* common element in the {@code a1} and {@code a2} arrays respectively.
* Common elements are indexed according to their order in the
* {@code a1} array.
* @param <E> the type of array element
* @param a1 an array of elements
* @param a2 an array of elements
* @return a two-dimensional array with indicies of common array
* elements
* @throws IllegalArgumentException if the {@code a1} or {@code a2} arrays
* have a duplicate element
* @throws NullPointerException if {@code a1 == null || a2 == null}
*/
public static <E> int[][] commonIndices(E[] a1, E[] a2) {
Map<E, Integer> map1 = arrayToMap(a1);
Map<E, Integer> map2 = arrayToMap(a2);
map1.keySet().retainAll(map2.keySet());
int[][] indices = new int[2][map1.size()];
int index = 0;
for (int j=0; j<a1.length; ++j) {
E id = a1[j];
if (map1.containsKey(id)) {
assert map2.keySet().contains(id);
indices[0][index] = map1.get(id);
indices[1][index++] = map2.get(id);
}
}
return indices;
}
/**
* Returns a map from array element to array index
* @param <E> the type of array element
* @param array an array
* @return a map from array element to array index
* @throws IllegalArgumentException if the {@code array}
* has a duplicate element
* @throws NullPointerException if {@code array == null}
*/
public static <E> HashMap<E, Integer> arrayToMap(E[] array) {
HashMap<E, Integer> map = new HashMap<>();
for (int j=0; j<array.length; ++j) {
E e = array[j];
if (map.containsKey(e)) {
String s = "duplicate element in array: " + e;
throw new IllegalArgumentException(s);
}
map.put(e, j);
}
return map;
}
}
|