How to asynchronously modify an array of Strings - java

I thought this was an interesting programming problem so I posted it even though I think I have a solution idea that is good enough, see (*). If anyone has an elegant solution I would love to see it!
I am working with a method that calls external library that does http requests to a server. I need to have K strings as input to be effective i.e. each invocation of the external resource is a HTTP request and I need to buffer up some data for effectiveness. (As an example let K be 200 and occurs as a token in a text with say 1% probability so I would need to process 20,000 tokens before finding the 200 input arguments).
Effectively what this does is: externalHTTP(commaDelimitedString) -> get info about each string. Example externalHTTP("foo,bar") -> ["information snippet 1","information snippet 2"]. Where "information snippet 1" is about "foo".
I want to replace the "foo" and "bar" in a long text (string) with the information snippets but only after my buffer for the HTTP request is full. I still want to continue reading the original string while waiting for this to happen.
The text is tokenized by splitting (so I am working with an array of strings).
I.e. I would not like to stop execution of my text processing just because I am waiting for K strings to buffer up.
At first I thought that I could store words as individual string objects that I later update but then I realized that strings are immutable so it is call by value.
(*) My second idea was to store indices of the words (foo and bar) and then in order insert the snippets back into the original string array when the http request is finished. Like
class doStuff {
String text[];
LinkedList<Integer> idxList = new LinkedList<Integer>();
public doStuff(String[] t) {
text = t;
int i = 0;
for (String token : text) {
if (shouldReplaceToken(token)) {
replaceToken(i);
}
i++;
//do other work with the tokens
}
}
void replaceToken(int i) {
idxList.add(i);
if (++count > buffSize) {
count = 0;
String commaDelim = "";
ListIterator<Integer> it = idxList.getListIterator(0);
while (it.hasNext()) {
commaDelim += text[it.next()]+",";
}
String[] http_response = http_req(commaDelim);
for (String snippet : http_response) {
idx = idxList.poll(); //this is not elegant, dependent on FIFO order
text[Idx] = snippet;
}
}
}
}
To complicate things further is that I want to process several longer texts so i would have need to have a matrix of String arrays, one for each text.
I don't like the class known reference
String[] text
or they way I deal with indices in this code...
Hoping to see some suggestions :)
Edit: changed a bit to be more clear. I cant really say what I am looking up, non-disclosure etc, sorry. Some names might be different from java (bit only small difference).

Ok... Here's an attempt to fully answer your question with example code.
I've never played with threads much, so I figured I'd try to learn something tonight.
This solution uses threads to allow the http request to take place asynchronously.
The asynchronous request is simulated by using Thread.sleep().
My test case is primitive: the main class just sleeps for 30 sec to wait for everything to finish up.
Like I said, I'm new to Thread programming, so I probably overlooked something.
Hopefully this gets you started in the right direction...
/**
* A class that asynchronously replaces text in an
* array of strings by using helper threads.
*/
public class TextReplacer {
private final int bufferSize;
List<String> wordList = new ArrayList<String>();
List<Integer> indexList = new ArrayList<Integer>();
int bufferPosition = 0;
int lastPosition = 0;
public TextReplacer(String[] a, int n) {
bufferSize = n;
if (a != null) {
wordList = Arrays.asList(a);
}
}
public void replaceText() {
int i = 0;
for (String thisWord : getWordListCopy()) {
if (shouldReplaceToken(thisWord)) {
indexList.add(i);
processTextReplacement();
}
i++;
}
}
private void processTextReplacement() {
if (isBufferReady()) {
int currentPos = lastPosition;
replaceStrings(getCsv(), currentPos);
}
}
/** Uses a thread to replace strings in wordList. */
private void replaceStrings(String csv, int pos) {
new ReplacerThread(wordList, indexList, csv, pos, bufferSize).start();
}
private String getCsv() {
StringBuilder csv = new StringBuilder();
for (int i = 0; i < bufferSize; i ++) {
int idx = indexList.get(lastPosition++);
csv.append(wordList.get(idx)).append(",");
}
return csv.toString();
}
private boolean isBufferReady() {
bufferPosition++;
return ( bufferPosition % bufferSize == 0 );
}
private List<String> getWordListCopy() {
List<String> listCopy = new ArrayList<String>();
listCopy.addAll(wordList);
return listCopy;
}
/**
* Simulates a 10% replacement rate by only
* returning true for input that ends with a 3.
*/
private boolean shouldReplaceToken(String s) {
return s.endsWith("3");
}
public List<String> getWordList() {
return wordList;
}
public String[] getWordArray() {
return wordList.toArray(new String[0]);
}
}
/**
* A thread that sleeps for up to 8 seconds, then
* replaces a bunch of words in the list that is
* passed to it in its constructor.
*/
public class ReplacerThread extends Thread {
List<String> originalWords;
List<Integer> indices;
String wordCsv;
String[] replacementWords;
int startPos;
int bufferSize;
int maxSleepMillis = 8000;
int sleepMillis = getSleepMillis();
int threadNum; // for debugging
String prefix = new String(); // for debugging
/** Create a new thread. */
public ReplacerThread(List<String> o, List<Integer> i,
String c, int p, int n) {
originalWords = o;
indices = i;
wordCsv = c;
startPos = p;
bufferSize = n;
threadNum = startPos / bufferSize;
int count = 0;
while (count++ < threadNum) {
prefix += " ";
}
}
#Override
public void run() {
replacementWords = httpReq(wordCsv);
for (int i = 0; i < bufferSize; i ++) {
int pos = startPos + i;
int idx = indices.get(pos);
originalWords.set(idx, replacementWords[i]);
}
print("Thread #" + threadNum + " COMPLETE");
}
/** Simulate an asynchronous http request by using Thread.sleep */
private String[] httpReq(String s) {
try {
printSleepMessage();
sleep(sleepMillis);
}
catch (InterruptedException ex) {}
String[] repText = s.split(",");
for (int i = 0; i < repText.length; i++) {
repText[i] = repText[i].replace("Line", "Funky Line");
}
return repText;
}
private void printSleepMessage() {
int ms = sleepMillis / 1000;
print("Thread #" + threadNum + " SLEEP(" + ms + ")");
}
private int getSleepMillis() {
Double ms = maxSleepMillis * Math.random();
return ms.intValue();
}
public void print(Object o) {
String s = (o == null ? "null" : o.toString());
System.out.println(prefix + s + "\n");
}
}
/** A class that tests my funky solution. */
public class Main {
static String inputFile = "test-input.txt";
static int bufferSize = 50;
public static void main(String[] args) {
String[] theInput = readInput();
TextReplacer testItem = new TextReplacer(theInput, bufferSize);
testItem.replaceText();
try {
// wait 40 seconds for everything to happen
Thread.sleep(40000);
}
catch (InterruptedException ex) { }
dumpOutput(testItem.getWordArray());
}
public static String[] readInput() {
File inFile = new File(inputFile);
List<String> lineList = new ArrayList<String>();
try {
BufferedReader buff = new BufferedReader(new FileReader(inFile));
String currentLine = buff.readLine();
while (currentLine != null) {
lineList.add(currentLine);
currentLine = buff.readLine();
}
}
catch (IOException ignoreMe) {}
print("Lines read: " + lineList.size());
return lineList.toArray(new String[0]);
}
public static void dumpOutput(String[] txt) {
long ms = System.currentTimeMillis();
String fileName = "output-" + ms + ".txt";
File outFile = new File(fileName);
try {
BufferedWriter buff = new BufferedWriter(new FileWriter(outFile));
for (String s : txt) {
buff.write(s);
buff.newLine();
}
}
catch (IOException ignoreMe) {}
print("Lines written: " + txt.length);
print("File: " + fileName);
}
public static void print(Object o) {
System.out.println(o == null ? "null" : o.toString());
}
}

Related

How to convert a 2d array into a 2d ArrayList in java?

I have a Java program that reads elements from a file, stores them in a 2d array and then it manipulates them according by commiting several operations.
I have already implemented the program by using a 2d array and now I want to find a way to turn this array into a 2d ArrayList, so I can manipulate these elements individually, like i did with the 2d array.
The program reads from a file that looks like this:
Jason,56
Martha,89
James,23
...
Here is my code attempting to convert my 2d array into a 2d ArrayList:
Keep in mind that I want all the names to be stored in the 1st column of the array/ArrayList and the age in the second column:
public class Testr {
public static void main(String[] args) throws FileNotFoundException, IOException {
Scanner sc = new Scanner(new BufferedReader(new FileReader("C:\\Users\\test.csv")));
int num_rows = countLines("C:\\Users\\test.csv");
System.out.println("Num of rows : " + num_rows);
int num_cols = countColumns("C:\\Users\\test.csv");
System.out.println("Num of cols : " + num_cols);
String[][] Entries_arr = new String[num_rows][num_cols];
while(sc.hasNextLine())
{
for(int i = 0; i < Entries_arr.length; i++)
{
String[] line;
line = sc.nextLine().trim().split(";");
for(int j = 0; j < line.length; j++)
{
Entries_arr[i][j] = line[j];
}
}
}
List<List<String>> Entries = new ArrayList<List<String>>();
for(int i = 0; i < Entries_arr.length; i++)
{
List<String> recs = new ArrayList<String>();
for(int j = 0; j < Entries_arr[i].length; j++)
{
recs.add(String.valueOf(Entries_arr[i][j]));
}
Entries.add(recs);
}
System.out.println(Entries);
}
//------------------------------------------------------------------------------------------------------------------------
public static int countLines(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
return (count == 0 && !empty) ? 1 : count;
} finally {
is.close();
}
}
//------------------------------------------------------------------------------------------------------
public static int countColumns(String filename) {
File file = new File(filename);
Scanner scanner;
try {
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return -1;
}
int number = 0;
if (scanner.hasNextLine()) {
number = scanner.nextLine().split(";").length;
}
scanner.close();
return number;
}
}
Any help is appreciated.
Going back to what was pointed out in the comments
Don't use a 2D array (or a 2D list) because you'd be using something similar to parallel arrays or parallel lists as your data structure. See Jon Skeet's Anti-Pattern: Parallel Collections blog for details.
Also by trying to solve your problem with a 2D array/list your code gets much more complicated than actually necessary (and for no good reason).
So how could an approach look like as pointed out in the comments?
Following code
reads a test file line by line,
processes each line into a User instance,
and collects them all into an ArrayList.
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileToList {
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(findCsvFile())) {
List<User> users = lines
.map(FileToList::process)
.flatMap(Optional::stream)
.collect(Collectors.toCollection(ArrayList::new));
System.out.println(users);
} catch (Exception e) {
System.out.println("Error when accessing the file\n");
e.printStackTrace();
}
}
static Path findCsvFile() throws Exception {
URL resource = FileToList.class.getResource(FileToList.class.getSimpleName() + ".class");
return Paths.get(resource.toURI()).resolveSibling("test.csv");
}
static Optional<User> process(String line) {
Optional<User> user = Optional.empty();
String[] values = line.split(",");
try {
String name = values[0];
int age = Integer.parseInt(values[1]);
User actualUser = new User(name, age);
user = Optional.of(actualUser);
} catch (Exception e) {
System.out.printf("Cannot process line: \"%s\" | Error: %s\n", line, e);
}
return user;
}
static class User {
private final String userFirstName;
private final int userAge;
User(String name, int age) {
this.userAge = age;
this.userFirstName = name;
}
public String getUserFirstName() {
return userFirstName;
}
public int getUserAge() {
return userAge;
}
#Override
public String toString() {
return String.format("%s(%d)", userFirstName, userAge);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return userAge == user.userAge &&
Objects.equals(userFirstName, user.userFirstName);
}
#Override
public int hashCode() {
return Objects.hash(userFirstName, userAge);
}
}
}
Running the above code against your example CVS file then outputs
[Jason(56), Martha(89), James(23)]
Note that Optional is used in the process method only to cover for the situation when a line from the CSV file cannot be processed into a new User object. The .flatMap(Optional::stream) then removes any potential optional (non-existing) user instances from the stream before collecting the actual users into an ArrayList.

How to convert ArrayList<String> to int[] in Java

I read Bert Bates and Katie Sierra's book Java and have a problem.
The Task: to make the game "Battleship" with 3 classes via using ArrayList.
Error: the method setLocationCells(ArrayList < String >) in the type
SimpleDotCom is not applicable for the arguments (int[])
I understand that ArrayList only will hold objects and never primatives. So handing over the list of locations (which are int's) to the ArrayList won't work because they are primatives. But how can I fix it?
Code:
public class SimpleDotComTestDrive {
public static void main(String[] args) {
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
int randomNum = (int) (Math.random() * 5);
int[] locations = {randomNum, randomNum+1, randomNum+2};
theDotCom.setLocationCells(locations);
boolean isAlive = true;
while(isAlive) {
String guess = helper.getUserInput("Enter the number");
String result = theDotCom.checkYourself(guess);
numOfGuesses++;
if (result.equals("Kill")) {
isAlive = false;
System.out.println("You took " + numOfGuesses + " guesses");
}
}
}
}
public class SimpleDotCom {
private ArrayList<String> locationCells;
public void setLocationCells(ArrayList<String> loc) {
locationCells = loc;
}
public String checkYourself(String stringGuess) {
String result = "Miss";
int index = locationCells.indexOf(stringGuess);
if (index >= 0) {
locationCells.remove(index);
if(locationCells.isEmpty()) {
result = "Kill";
} else {
result = "Hit";
}
}
return result;
}
}
public class GameHelper {
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0)
return null;
} catch (IOException e) {
System.out.println("IOException:" + e);
}
return inputLine;
}
}
convert ArrayList to int[] in Java
Reason for Basic Solution
Here's a simple example of converting ArrayList<String> to int[] in Java. I think it's better to give you an example not specific to your question, so you can observe the concept and learn.
Step by Step
If we have an ArrayList<String> defined below
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
Then the easiest solution for a beginner would be to loop through each list item and add to a new array. This is because the elements of the list are type String, but you need type int.
We start by creating a new array of the same size as the List
int[] numbers = new int[numbersInAList.size()];
We then iterate through the list
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
Then inside the loop we start by casting the String to int
int num = Integer.parseInt(numbersInAList.get(ndx));
But there's a problem. We don't always know the String will contain a numeric value. Integer.parseInt throws an exception for this reason, so we need to handle this case. For our example we'll just print a message and skip the value.
try {
int num = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
We want this new num to be placed in an array, so we'll place it inside the array we defined
numbers[ndx] = num;
or combine the last two steps
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
Final Result
If we combine all of the code from "Step by Step", we get the following
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
int[] numbers = new int[numbersInAList.size()];
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
try {
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
}
Important Considerations
Note there are more elegant solutions, such as using Java 8 streams. Also, it's typically discouraged to store ints as Strings, but it can happen, such as reading input.
I can't see where you call setLocationCells(ArrayList<String>) in your code, but if the only problem is storing integers into an ArrayList there is a solution:
ArrayList<Integer> myArray = new ArrayList<Integer>();
myArray.add(1);
myArray.add(2);
It is true that you can't use primitive types as generics, but you can use the Java wrapper types (in this case, java.lang.Integer).

Get next run from a text file

I am trying to write a function in Java that returns the next ascending sequence (run) from a txt file, let's say the return type of a function would be ArrayList.
My example file input.txt contains next values: 78123421. So in terms of runs that means the file has 4 runs: |78|1234|2|1|.
What am I trying to reach here is like when I would call this function from main() four times it should print something like
1.run: 78,
2.run: 1234,
3.run: 2,
4.run: 1
or just two calls should print
1.run: 78,
2.run: 1234
I have tryed to solve my problem using BufferedReader/FileReader and RandomAccessFile but no working solution so far, please help :/
So this is what I have so far. The main idea was to use RandomAccessFile and read from input as long as run condition is satisfied. But the reader reads one value more, that is why I use seek() to start reading at the right position when next function call happens. There must be a bug in the code, because it doesn't print all the runs or just an Exception fires.
import java.io.File;
import java.util.ArrayList;
import java.io.RandomAccessFile;
public class GetRunsFromFile
{
static long start = 0;
static long read_len = 0;
public static void main(String[] args) throws Exception
{
File in = new File("C:/Users/henrich/Desktop/Gimp.txt");
RandomAccessFile raf = new RandomAccessFile(in,"r");
ArrayList<Integer> current_run = new ArrayList<Integer>();
for(int i=1;i<=4;i++)
{
current_run = getNextRun(raf);
printArrayList(current_run);
}
raf.close();
}
private static ArrayList<Integer> getNextRun(RandomAccessFile raf) throws Exception
{
int v;
String line;
int val = Integer.MIN_VALUE;
ArrayList<Integer> run = new ArrayList<Integer>();
while((line=raf.readLine())!= null)
{
v = Integer.parseInt(line.trim());
if(v >= val)
{
read_len = raf.getFilePointer() - start;
start = raf.getFilePointer();
run.add(v);
val = v;
}
else
{
raf.seek(raf.getFilePointer() - read_len);
start = raf.getFilePointer();
return run;
}
}
return null;
}
private static void printArrayList(ArrayList<Integer> al)
{
for(int i=0; i<al.size(); i++)
{
System.out.print(al.get(i) + " ");
}
System.out.println();
System.out.println("------");
}
}
For more questions please let me know.
Note: It should work only for ascending runs and files of any length.
Thanks for the support.
There are several ways to do it.
solution 1
For instance call your function with an int and make it return an int refering to the number of the last printed char.
Run Exaple:
after the first run return 2 cause the length of print text is 2
after the second run return 6 cause the length of print text is 4 +2 from last loop... etc.
public int function(int startPoint){
// do stuff here
return lastIndexofPrintChar;
}
then call your function like this
loop{
int result=0;
result= function(x);
}
solution 2
You can also dublicate your file and remove every String you print.
private static void getNextRun()
{
try
{
BufferedReader br = new BufferedReader(new FileReader(new File("C:/Users/henrich/Desktop/Gimp.txt")));
br.skip(skip_lines);
int v;
String line;
int val = Integer.MIN_VALUE;
ArrayList<Integer> al = new ArrayList<Integer>();
while((line=br.readLine())!= null)
{
skip_lines += line.length()+2;
v = Integer.parseInt(line.trim());
if(v >= val)
{
al.add(v);
val = v;
}
else
{
skip_lines -= line.length() + 2;
printArrayList(al);
break;
}
}
br.close();
}
catch (Exception e){System.out.println("EOF");}
}

Creating array from reading a file

I have a file with the following:
5
212:Float On:Modest Mouse
259:Cherub Rock:Smashing Pumpkins
512:Won't Get Fooled Again:The Who
417:Teen Age Riot:Sonic Youth
299:PDA:Interpol
I need to create a array but I need to take into account the integer it starts with, then read the rest as strings taking into account the initial line containing only an integer. I've made the method to read the file and print, just don't know how to split it up.
An example of how to do it:
String s = "212:Float On:Modest Mouse"; // your input - a line from the file
String[] arr = s.split(":");
System.out.println(arr[0]); // your int
// The rest of the array elements will be the remaining text.
// You can concatenate them back into one string if necessary.
you can read file using Scanner
readlines = new Scanner(filename);
while(readlines.hasNextLine())
{
String line = readlines.nextLine();
String[] values = line.split(":");
int firstColumn = -1;
if (values.length > 0) {
try {
firstColumn = Integer.parseInt(values[0]);
} catch (NumberFormatException ex) {
// the value in the first column is not an integer
}
}
}
I've grown a habit of reading the entire file into a List, then handling the List in memory. Doing this is not the only option.
Once I have the file read in, I look at the first line to know how many tracks to expect in the remaining file. I then would loop through the remaining List to either get the number of tracks from the first line or until I reach the end of the list, in the event that the number of tracks (from the first line) exceeds the actual amount of tracks that are in the file.
As I go through the tracks I would use substring to break the line apart, and convert just the first part.
Update
Base on your comment, I've updated to use split instead of substring. Then some basic alignment formatting for output
public static void main(String[] args) throws Exception {
String yourFile = "path to your file.txt";
List<String> yourFileLines = new ArrayList<>(Files.readAllLines(Paths.get(yourFile)));
// You know the first line is suppose to be the number of tracks so convert it to a number
int numberOfTracks = Integer.valueOf(yourFileLines.get(0));
// Either go to the number of tracks or till the end of file
List<Track> tracks = new ArrayList<>();
for (int i = 1; (i <= numberOfTracks && i < yourFileLines.size()); i++) {
String currentFileLine = yourFileLines.get(i);
String[] currentFileLinePieces = currentFileLine.split(":");
Track currentTrack = new Track();
currentTrack.TrackTime = Integer.valueOf(currentFileLinePieces[0]);
currentTrack.TrackTitle = currentFileLinePieces[1];
currentTrack.TrackArtist = currentFileLinePieces[2];
tracks.add(currentTrack);
}
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "TITLE", "ARTIST", "TIME"));
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "-----", "------", "----"));
for (Track currentTrack : tracks) {
System.out.println(currentTrack);
}
}
public static class Track {
public int TrackTime;
public String TrackTitle;
public String TrackArtist;
#Override
public String toString() {
return String.format("%-20s\t\t%-20s\t\t%-20d", TrackTitle, TrackArtist, TrackTime);
}
}
Results:
Here's an example using a Scanner, and breaking everything into methods. You should be able to use List and ArrayList. Results are the same.
public static void main(String[] args) throws Exception {
String yourFile = "data.txt";
List<String> yourFileLines = readFile(yourFile);
if (yourFileLines.size() > 0) {
// You know the first line is suppose to be the number of tracks so convert it to a number
int numberOfTracks = Integer.valueOf(yourFileLines.get(0));
List<Track> tracks = getTracks(numberOfTracks, yourFileLines);
printTracks(tracks);
}
}
public static List<String> readFile(String pathToYourFile) {
List<String> yourFileLines = new ArrayList();
try {
File yourFile = new File(pathToYourFile);
Scanner inputFile = new Scanner(yourFile);
while(inputFile.hasNext()) {
yourFileLines.add(inputFile.nextLine().trim());
}
} catch (Exception e) {
System.out.println(e);
}
return yourFileLines;
}
public static List<Track> getTracks(int numberOfTracks, List<String> yourFileLines) {
List<Track> tracks = new ArrayList();
// Either go to the number of tracks or till the end of file
for (int i = 1; (i <= numberOfTracks && i < yourFileLines.size()); i++) {
String currentFileLine = yourFileLines.get(i);
String[] currentFileLinePieces = currentFileLine.split(":");
Track currentTrack = new Track();
currentTrack.TrackTime = Integer.valueOf(currentFileLinePieces[0]);
currentTrack.TrackTitle = currentFileLinePieces[1];
currentTrack.TrackArtist = currentFileLinePieces[2];
tracks.add(currentTrack);
}
return tracks;
}
public static void printTracks(List<Track> tracks) {
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "TITLE", "ARTIST", "TIME"));
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "-----", "------", "----"));
for (Track currentTrack : tracks) {
System.out.println(currentTrack);
}
}
public static class Track {
public int TrackTime;
public String TrackTitle;
public String TrackArtist;
#Override
public String toString() {
return String.format("%-20s\t\t%-20s\t\t%-20d", TrackTitle, TrackArtist, TrackTime);
}
}

how to iterate through an array list of class type

I have two classes A and B. I want to access an array list in A from B. The array list is of class C type, which stores objects(packets). I would like to know if there is any way to iterate through the list and get specific data from each packet.
public class PcapStream
{
PcapParser objPcapParser = new PcapParser();
PcapDef numPackets = new PcapDef();
int listSize = numPackets.getMaxPackets();
public void findStream()
{
final ListIterator<PcapDef> packetIterator = objPcapParser.packet_list.listIterator();
while(packetIterator.hasNext())
{
for(final int i=0; i<=listSize;i++)
{
I started off with something like this. Not sure how it works. Class B is PcapStream, Class A is PcapParser, Class C is PcapDef
ListIterator packetIterator = objPcapParser.packet_list.listIterator();
while(packetIterator.hasNext())
{
for(int i=0; i<listSize; i++ )
{
PcapDef packet1 = (PcapDef) packetIterator.next();
PcapDef packet2 = packetIterator; //here I would like to get the 2nd object from the list, not sure how to get that at this point.
}
}
public int compare(final PcapDef packet1, final PcapDef packet2)
{
return 0;
}
I'm still working on it. At this point this is what I have
public void findStream()
{
try
{
for(int i=0;i<listSize;i++)
{
final List <PcapDef> list = new ArrayList<PcapDef>();
final PcapDef packet1 = objPcapParser.packet_list.get(i);
checkPackets(packet1, list, i);
}
}
catch(final IndexOutOfBoundsException e)
{
System.out.println("Exception : " + e);
}
final Set packetSet = Stream.entrySet();
final Iterator setIterator = packetSet.iterator();
while(setIterator.hasNext())
{
final Map.Entry packetEntry = (Map.Entry) setIterator.next();
System.out.print(packetEntry.getKey() + ": ");
System.out.println(packetEntry.getValue());
}
}
private void checkPackets(final PcapDef packet1, final List<PcapDef> list, final int i)
{
for(int j=1;j<listSize && j!=i;j++)
{
final PcapDef packet2 = objPcapParser.packet_list.get(j);
final int value = compare(packet1,packet2);
if(value == 0)
{
list.add(packet1);
list.add(packet2);
checkPackets(packet2, list, i);
}
else
{
Stream.put(i,list); //add list to hashmap
}
}
}
#Override
public int compare(final PcapDef packet1, final PcapDef packet2)
{
final String header1 = packet1.getHeader();
final String header2 = packet2.getHeader();
final String src_port1 = packet1.getSrc_port();
final String dst_port2 = packet2.getDst_port();
final String src_port2 = packet2.getSrc_port();
final String dst_port1 = packet1.getDst_port();
System.out.println(header1 + header2);
int flag = 1;
try{
if(header1.equalsIgnoreCase(header2))
{
if((src_port1.substring(10).equalsIgnoreCase(dst_port2.substring(10))) && (src_port2.substring(10).equalsIgnoreCase(dst_port1.substring(10)) )
{
flag = 0;
return flag;
}
}
}
#Andy This is what I wrote so far. Problems I'm facing: Duplicates are being generated and hashmap entries are not continuous, I mean like index 0,1,2.. instead few locations are empty. Due to this if I give very large files as input to my program it is throwing me an indexoutofboundsexception. I'm a beginner and trying my best. Kindly, help.
You can use the Iterator.next() method to get the next list member. Each call to next() advances to the next list member.
while(packetIterator.hasNext())
{
PCapDef packet = packetIterator.next();
...
}
EDIT:
And you can use the Iterator.get(int) method to get a list member by index.
while(packetIterator.hasNext())
{
PCapDef packet = packetIterator.next();
for(int i=0; i<listSize; i++ )
{
PcapDef packet2 = objPcapParser.packet_list.get( i )
...
}
}

Categories