Thursday, September 13, 2018

Repeating strings with a separator in Java

The problem of joining strings with a separator is a very common one in programming, but is surprising the number of solutions that different programmers find to that simple task.
Recently I had to repeat a given string ("?" for example) a given number of times but adding a separator between each string ("," for example). I searched for that code in other places of the project and I found many ways, including these:
if (n > 0) {
 for (int i = 1; i < n; i++) {
  buf.append("?,");
 }
 buf.append("?");
}

if (n > 0) {
 for (int i = 0; i < n; i++) {
  buf.append("?,");
 }
 buf.setLength(buf.length() - 1);
}

for (int i = 0; i < n; i++) {
 buf.append("?");
 if (i < n - 1) {
  buf.append(",");
 }
}

boolean first = true;
for (int i = 0; i < n; i++) {
 if (first) {
  first = false;
 } else {
  buf.append(",");
 }
 buf.append("?");
}
To stop this madness, I decided to create a method for reducing all those variations to simpler and less error-prone calls:
/**
 * Appends a string to a buffer a specified number of times,
 * optionally inserting another string as a separator.
 *
 * @param sb The buffer that will have the string appended, if null a new one is created.
 * @param str The string to append.
 * @param n The number of times that the string will be appended.
 * @param sep An optional separator appended between two strings.
 *
 * @return The specified buffer with the string appended or a new one if it was null.
 */
public static StringBuilder repeatAppend(StringBuilder sb, String str, int n, String sep) {
  if (sb == null) {
    sb = new StringBuilder();
  }
  if (n > 0) {
    sb.append(str);
    if (sep != null) {
      for (int i = 1; i < n; i++) {
        sb.append(sep).append(str);
      }
    } else {
      for (int i = 1; i < n; i++) {
        sb.append(str);
      }
    }
  }
  return sb;
}

Be free to use it in your project and happy coding!

Update: Apache Commons StringUtils.repeat(str, sep, n) and Java Collections.nCopies(n, str) with String.join(sep, collection) are alternatives to this method, but our method allows adding to an existing StringBuilder and the others need to create it and destroy it for that. Added return sb; to allow an inline use.


Tuesday, April 11, 2017

Java class for faster searching of substrings in HashMap

Creating objects in Java requires the allocation of system memory, which is a very complex operation, so many algorithms will be faster when it is avoided. This Substring class allows you to search a portion of a String in a HashMap (one with String keys) without having to create any object. Every time the String.substring method is called, a new object is allocated for the substring (only the internal array is shared), so the solution is searching in the HashMap without using a real String as the key, which can be 2 times faster:

...
Substring substr = new Substring();
for (...) { //lots of repetitions
    String str = ...; int start = ...; int end = ...;
    //obj = hmap.get(str.substring(start, end)); //before
    obj = hmap.get(substr.setSubstring(str, start, end));
    if (obj != null) { ... }
}


Because the Java memory management is so efficient, the use of this class will only be faster if your program needs to search for thousands of substrings and you reuse the same Substring object. A similar idea could also be applied to search for the uppercase version of a String in a HashMap without creating new objects (when calling to String.toUpperCase a new object is created if a lowercase character is found). This one is left as an exercise for the reader. Enjoy!

Sunday, September 4, 2016

Javascript Text Replacing Tool

JS Replace is a simple tool for programmers to copy&paste multiple text lines and make automatically changes on all of them by editing the Javascript code box. Tired of building throw-away scripts or complex SQL queries or repetitive Spreadsheet formulas to make simple changes on many rows of data, I developed a simple but powerful javascript tool to assist in such tasks. Use it!

 


Sunday, July 24, 2016

Simple ToDo-List Javascript application for the smartphone

I wrote a simple ToDo-List application in Javascript to use it in the smartphone. To try it, you need to download the todo-list.html file and then open it with your web browser (Note: not every smartphone lets you open correctly the downloaded HTML files):


It is just a HTML document that "saves" the items as parameters in the web browser address. This approach gives me persistence, Undo and Redo operations for free, just having it opened in a tab of the web browser (Note: it will work only if your web browser is configured to remember your opened tabs). Enjoy it!

Friday, May 15, 2015

Mark IV Special Coffee Maker API implementation

In his book "UML for Java Programmers", Robert C. Martin (from Object Mentor) explains an object oriented software design problem: Writing an implementation of the software for the fictional Mark IV Special Coffee Maker. The solution must use the low-level API of the hardware that controls the different parts of the machine, which is provided as the CoffeeMakerAPI Java interface. Robert also published the complete Mark IV Special Coffee Maker chapter for us.

I am not here to give another solution for the problem. Instead, I wrote the CoffeeMakerGUI application, that contains a CoffeeMakerAPI implementation that lets you to manually test your solution by using a simulated Coffee Maker machine:


To compile it using a Java compiler, you need the CoffeeMakerAPI Java interface (given in the mentioned chapter) and also the following interface:

   public interface CoffeeMakerImpl {
      void createComponents(CoffeeMakerAPI api);
      void pollComponents();
   }

You can run the application without parameters, and a help message will be printed, but to test your solution you have to connect it with CoffeeMakerGUI, and to do it you must pass as the first argument of the program a class implementing the above CoffeeMakerImpl interface and having a default constructor. So the command to run it could be, for example:
java CoffeeMakerGUI MyCoffeeMakerImpl

The program will instance that passed class and will call to createComponents passing a reference of the CoffeeMakerAPI implementation. Then, it will call to the pollComponents periodically to "wake up" your implementation.

Thanks to Uncle Bob for publishing that interesting problem and solution!

Sunday, December 28, 2014

Simple JavaScript function to compare and sort localized strings

A recurring problem in JavaScript is sorting localized strings, that is, strings having characters from outside of the ASCII [A-Za-z] range, like for example the Spanish characters áéíóúüñ (and their uppercase equivalents).

For this problem I wrote the JavaScript function getLocaleStrCmpFn, which returns a function to compare and sort strings depending on the order given as parameter, for example, to sort an array of strings having Spanish characters you can do:

var ordES = ['AaÁá','Bb','Cc','Dd','EeÉé','Ff','Gg','Hh',
'IiÍí','Jj','Kk','Ll','Mm','Nn','Ññ','OoÓó','Pp','Qq',
'Rr','Ss','Tt','UuÚúÜü','Vv','Ww','Xx','Yy','Zz'];
var fnES = getLocaleStrCmpFn(ordES);

var arr = ['Álamo','abedul','Arce','abeto','Castaño','acacia'];
arr.sort(fnES);

Other ways to do it are the localeCompare function with additional non-standard arguments or the future JavaScript Internationalization API, but both are not supported in many versions of major browsers, so the locale-str-cmp.js solution is an easy way to sort strings for a specific locale or to create custom comparison functions. What do you think?

Thursday, November 13, 2014

Program to draw Tangram figures in SVG

The Tangram is an ancient Chinese game consisting in 7 geometrical flat pieces which must be put together to form a given figure, usually printed in paper. The solution for a given problem can be in another page, for example, this is how you form a square with the Tangram pieces:


I wrote a program in Perl called draw-tangram to create images of Tangram figures. To create a figure you need to write a description of the position of the pieces in a text file, in a simple format created for the program. Then you can choose to create images for the problem or the solution. For example:


To make this figure I first wrote the following instructions in a text file:

<3/4> a-b-c-d-a <0,6,4,2> [1,1,1,1];
<3/4> b-e-f-c-b <7,6,3,2> [0:1,1,0:1,1];
<3/4> f-g-h-f <3,6,1> [1,0:1,1];
<1/2> h-i-j-h <4,7,2> [2,0:2,2];
<1/2> i-k <7> [1];
<1/2> k-l-m-k <7,5,2> [1,1,0:1];
<1/2> k-o-n-k <3,5,0> [2,2,0:2];
<1/2> n-q <1> [0:1];
<1/2> q-s-r-q <1,4,7> [0:1,2,0:1];

Numbers between < and > are angles and numbers between [ and ] are lengths. The program helps you to create this because without parameters it prints the names of the points of the figure. To run the program you need Perl installed, and then you can write, for example:

perl draw-tangram.pl figure.txt

Then you can open the generated SVG file in a web browser to see the result. After that, you can use a program for editing vector graphics like Inkscape if you want a PNG or JPEG image. Enjoy it!