Dan Dan - 4 months ago 15
Java Question

Remove the need to iterate the list for every element

I constructed a fairly simple program which takes information from a

.txt
file and puts it in a list, sorts it, and then it removes duplicates by putting it in a
TreeSet
.

If you look at
countInstance()
and how it is called, you will see that for every iteration of the
TreeSet
the method is run and then it iterates the list
dataToSplit
multiple times. I believe it iterates the list 30 times in this specific case.

The Question
Is there a way I can remove the need to iterate the list so many times and yet achieve the same results?

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class TallyCounter {
private void tallyCount(File commaSeperated) {
List<String> dataToSplit = new ArrayList<String>();
Set<String> set;

try {
BufferedReader br = new BufferedReader(new FileReader(commaSeperated));
String currentLine;
while ((currentLine = br.readLine()) != null) {
String[] tempArray = currentLine.split(",");
for(String s : tempArray) {
dataToSplit.add(s.replaceAll("\t", "").replaceAll("\n", "").trim());
}
}

br.close();
} catch(Exception e) {
e.printStackTrace();
}

dataToSplit.sort(new AlphanumComparator());
set = new TreeSet<String>(dataToSplit);


System.out.println("String Tally Count");
for(String s : set) {
System.out.println(countInstance(s, dataToSplit));
}
}

private String countInstance(String s, List<String> l) {
int count = 0;

for(String temp : l) {
if(s.equals(temp)) {
count++;
}
}

int rSpace = (10 - count) / 2;

String repeated = new String(new char[count]).replace("\0", "|");
String space = new String(new char[rSpace]).replace("\0", " ");

return " " + s + " " + space + repeated + " " + space + Integer.toString(count);
}


public static void main(String[] args) {
TallyCounter tC = new TallyCounter();
tC.tallyCount(new File("src/txt.txt"));
}
}





Extra details

AlphanumComparator.java

import java.util.Comparator;

public class AlphanumComparator implements Comparator<Object>
{
private final boolean isDigit(char ch)
{
return ch >= 48 && ch <= 57;
}

/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
private final String getChunk(String s, int slength, int marker)
{
StringBuilder chunk = new StringBuilder();
char c = s.charAt(marker);
chunk.append(c);
marker++;
if (isDigit(c))
{
while (marker < slength)
{
c = s.charAt(marker);
if (!isDigit(c))
break;
chunk.append(c);
marker++;
}
} else
{
while (marker < slength)
{
c = s.charAt(marker);
if (isDigit(c))
break;
chunk.append(c);
marker++;
}
}
return chunk.toString();
}

public int compare(Object o1, Object o2)
{
if (!(o1 instanceof String) || !(o2 instanceof String))
{
return 0;
}
String s1 = (String)o1;
String s2 = (String)o2;

int thisMarker = 0;
int thatMarker = 0;
int s1Length = s1.length();
int s2Length = s2.length();

while (thisMarker < s1Length && thatMarker < s2Length)
{
String thisChunk = getChunk(s1, s1Length, thisMarker);
thisMarker += thisChunk.length();

String thatChunk = getChunk(s2, s2Length, thatMarker);
thatMarker += thatChunk.length();

// If both chunks contain numeric characters, sort them numerically
int result = 0;
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
{
// Simple chunk comparison by length.
int thisChunkLength = thisChunk.length();
result = thisChunkLength - thatChunk.length();
// If equal, the first different number counts
if (result == 0)
{
for (int i = 0; i < thisChunkLength; i++)
{
result = thisChunk.charAt(i) - thatChunk.charAt(i);
if (result != 0)
{
return result;
}
}
}
} else
{
result = thisChunk.compareTo(thatChunk);
}

if (result != 0)
return result;
}

return s1Length - s2Length;
}
}


txt.txt

5.00, 5.14, 5.01, 4.90, 5.02, 5.18, 5.04, 5.07, 4.95, 5.05
5.05, 4.82, 4.97, 5.04, 4.98, 5.12, 5.08, 4.96, 5.02, 4.93
5.12, 5.04, 5.13, 4.94, 5.06, 5.00, 4.92, 5.17, 5.08, 4.99
5.07, 5.15, 5.01, 4.95, 5.11, 5.22, 5.08, 4.86, 4.97, 5.14
5.03, 5.14, 5.06, 4.88, 4.96, 5.04, 4.96, 5.09, 4.93, 5.03





Foot Note

I apologise for how strange the output looks when it is run. That is only because I have yet too implement a
JTable
to store the information

Answer

Use a HashMap<String,Integer> countMap and iterate through the strings once. With each temp you'll find, add 1 to the respective value countMap.get(temp) in the HashMap.