Your tokenism is quite unusual (with separators preserved) that you probably want to do it yourself. Basically, if you see a token corresponding to a note, pass it to the transponder. Otherwise, follow the space bar. Use the while loop to move through notes. Here is the code that does just that:
private static final Transposer transposer = new Transposer(); public static void main(String[] args) { String chordLine = "CG Am C"; String transposed = transposeChordLine(chordLine); System.out.println(transposed); } private static String transposeChordLine(String chordLine) { char[] chordLineArray = chordLine.toCharArray(); StringBuilder transposed = new StringBuilder(); StringBuilder currentToken = new StringBuilder(); int index = 0; while(index < chordLine.length()) { if(chordLineArray[index] == ' ') { transposed.append(' '); currentToken = processToken(transposed, currentToken); } else { currentToken.append(chordLineArray[index]); } index++; } processToken(transposed, currentToken); return transposed.toString(); } private static StringBuilder processToken(StringBuilder transposed, StringBuilder currentToken) { if(currentToken.length() > 0) { String currentChord = currentToken.toString(); String transposedChord = transposer.transpose(currentChord, 2); transposed.append(transposedChord); currentToken = new StringBuilder(); } return currentToken; }
Note. You have some stylistic issues with your code. You can initialize your permanent chord cards in the fields themselves; By doing this in the constructor, you overwrite them, do unnecessary work, and potentially cause problems, especially in multi-threaded code. Just make them inline in the field declaration. It is also useful to wrap them in Collections.unmodifiableList , so they cannot be changed when your code runs, and therefore facilitate a random error.
In addition, you should not store the inc variable in the field, just pass it as an argument. Thus, if you use the same object twice, it does not save state and therefore is thread safe. I know that it does not matter for your current program, but itβs good to learn these habits now. Here's the Transposer class changed:
public class Transposer { private static final List<String> keysSharp = Collections.unmodifiableList(Arrays.asList("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")); private static final List<String> keysFlat = Collections.unmodifiableList(Arrays.asList("C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B")); public String transpose(String chord, int inc) { String newChord; if (chord.contains("/")) { String[] split = chord.split("/"); newChord = transposeKey(split[0], inc) + "/" + transposeKey(split[1], inc); } else newChord = transposeKey(chord, inc); return newChord; } private String transposeKey(String key, int inc) {