I am trying to add marker New direction to the arrayList mergeArray when I found the second 3 value in the buffer arrayList but I am always getting the first 3 value in the ArrayList. How can I get the second one after Amsterdam?
I appreciate any help.
output:
paris
3
water
ball
money
Amsterdam
3
door
output should looks like this:
paris
3
water
ball
money
New direction
Amsterdam
3
door
Code:
public static void main(String[] args) {
ArrayList<String> buffer = new ArrayList<String>();
ArrayList<String> mergeArray = new ArrayList<String>();
String route = "3";
String direction = "paris";
String start = "Amsterdam";
buffer.add("paris");
buffer.add("3");
buffer.add("water");
buffer.add("ball");
buffer.add("money");
buffer.add("Amsterdam");
buffer.add("3");
buffer.add("door");
for (String line : buffer) {
if (line.equals(route)) {
mergeArray.add(line);
int index = buffer.indexOf(line);
String prevElement = buffer.get(index - 1);
if (prevElement == direction) {
String addElem = buffer.get(index + 1);
mergeArray.add(addElem);
} else if (prevElement == start) {
mergeArray.add("New direction");
}
}
}
for (String key : mergeArray) {
System.out.println(key);
}
}
Do not use indexOf as it will always retrieve the index of the first appearance.
Keep an auxiliary index variable and use it in your loop:
int auxIndex = 0;
for (String line : buffer) {
if (line.equals(route)) {
mergeArray.add(line);
String prevElement = buffer.get(auxIndex - 1);
if (prevElement.equals(direction)) {
String addElem = buffer.get(auxIndex + 1);
mergeArray.add(addElem);
} else if (prevElement.equals(start)) {
mergeArray.add("New direction");
}
}
auxIndex++
}
also add safety checks so the index will not under/over-flow
Try using a clasic for, instead of one that uses Iterable
for (int i=0; i<buffer.size(); i++) {
String line = buffer.get(i);
if (line.equals(route)) {
mergeArray.add(line);
String prevElement = buffer.get(i - 1);
if (prevElement == direction) {
String addElem = buffer.get(i + 1);
mergeArray.add(addElem);
} else if (prevElement == start) {
mergeArray.add("New direction");
}
}
}
Also, consider checking for over/underflow problems. You refer to index-1 and index+1, which will cause trouble if the appearance is on the first or last position.
Related
I would like to enquire or get some reference as to how can I dynamically create a counter for each month if the exists ? Currently, I am retrieving the dates from a CSV file and store it in an ArrayList, from there I am comparing the dates to check whether if such month exists. If the month exists then "counter++". Afterwards, store the counter in a hashmap. I understand my code currently is an inefficient way of coding. How could I make it better ?
CODE
public HashMap<String, Integer> getDataPoint() {
//My function code
HashMap<String, Integer> numberOfPost = new HashMap<String, Integer>();
int janCounter = 0;
int febCounter = 0;
int marCounter = 0;
int aprCounter = 0;
int mayCounter = 0;
int juneCounter = 0;
int julyCounter = 0;
int augCounter = 0;
int septCounter = 0;
int octCounter = 0;
int novCounter = 0;
int decCounter = 0;
String pattern = "MMM";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
OpenCsvReader reader = new OpenCsvReader();
ArrayList <STPost> STArray = reader.loadST("file_path");
Iterator STitr = STArray.iterator();
while (STitr.hasNext()) {
STPost St = (STPost) STitr.next();
Date retrievedate = St.getTime();
String strDate = sdf.format(retrievedate);
if(strDate.equals("Jan")) {
janCounter++;
}
else if (strDate.equals("Feb")) {
febCounter++;
}
else if (strDate.equals("Mar")) {
marCounter++;
}
else if (strDate.equals("Apr")) {
aprCounter++;
}
else if (strDate.equals("May")) {
mayCounter++;
}
else if (strDate.equals("June")) {
juneCounter++;
}
else if (strDate.equals("July")) {
julyCounter++;
}
else if (strDate.equals("Aug")) {
augCounter++;
}
else if (strDate.equals("Sept")) {
septCounter++;
}
else if (strDate.equals("Oct")) {
octCounter++;
}
else if (strDate.equals("Nov")) {
novCounter++;
}
else if (strDate.equals("Dec")) {
decCounter++;
}
numberOfPost.put("January", janCounter);
numberOfPost.put("Feburary", febCounter);
numberOfPost.put("March", marCounter);
numberOfPost.put("April", aprCounter);
numberOfPost.put("May", mayCounter);
numberOfPost.put("June", juneCounter);
numberOfPost.put("July", julyCounter);
numberOfPost.put("August", augCounter);
numberOfPost.put("September", septCounter);
numberOfPost.put("October", octCounter);
numberOfPost.put("November", novCounter);
numberOfPost.put("December", decCounter);
}
return numberOfPost
}
You can create an array of months and check if value exists there using indexOf method.
String months = "JanFebMarAprMayJunJulAugSepOctNovDec";
Integer idx = months.indexOf(strDate);
Thereafter you can use SimpleDateFormat("MMMM") pattern to put and get it into your map.
if(idx > -1) {
String longDate = new SimpleDateFormat("MMMM").format(retrievedate);
Integer current = numberOfPost.get(longDate);
if (current == null) {
current = 1;
} else {
current += 1;
}
numberOfPost.put(longDate, current);
}
Thereafter, you can use map iterator to display content of map.
You already have a good start. Using a the hash map will make the code much tidier.
You can replace all those if statements and put statements with the code below:
if (!numberOfPosts.containsKey(strDate)) {
numberOfPosts.put(strDate, 0);
}
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1);
The if statement will create a dictionary entry if there is not one with the key of strDate. The value of the entry is set to 0.
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1)
The line above increments by 1 the dictionary entry with the key of strDate.
I'm having trouble writing a for-each loop that searches the arraylist and returns the county's name within the continent that has the highest gdp. Here's my code for it right now. (ElementsList is the original ArrayList)
public Country highestGdp(String continent) {
boolean flag;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
ArrayList<Country> TMP1 = new ArrayList<Country>();
TMP1.add(cont);
for (Country gdp : TMP1) {
double max = 0;
if (max < gdp.getGDP()) {
max = gdp.getGDP();
}
if (gdp.getGDP() == max) {
ArrayList<Country> TMP2 = new ArrayList<Country>();
TMP2.add(gdp);
}
return gdp;
}
}
}
return null;
}
Each time you find a country in the right continent, you can check to see if it is greater than the max so far. Don't need to loop through all of them each time.
public Country highestGdp(String continent) {
boolean flag;
Country maxCountry = null;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
if (maxCountry == null) maxCountry = cont;
if (maxCountry.getGDP() < gdp.getGDP()) {
maxCountry = cont;
}
}
}
return maxCountry;
}
Sorry for saying it but Your code is a little messy ;)
To shortly solve Your problem, try to move max declaration before the loop like this:
[...]
double max = 0;
for(Country gdp : TMP1){
[...]
We can see that TMP2 is completely useless, remove it:
// ArrayList<Country> TMP2 = new ArrayList<Country>();
// TMP2.add(gdp);
You create TMP1 list always with only 1 element and then iterate over it. This is also useless, You can do the code directly on the element You are adding to the list.
First iteration over ElementList is a list of Country elements, but the element You iterate is called cont (=continent) which is a Continent and not the Country. Is it intended to use Country class to cover both: Countries and Continents? Do You plan to have a tree structure like "Continents contains many Countries"?
Final code to solve problem from Your original question should be like this:
public Country highestGdp(String continent){
Country countryWithMaxGdp = null;
for(Country cont: ElementsList ){
if(cont.getContinent().equals(continent)){
if(countryWithMaxGdp == null || countryWithMaxGdp.getGDP() < cont.getGDP()){
countryWithMaxGdp = cont;
}
}
}
return countryWithMaxGdp;
}
So I have a program written so far that reads in a csv file of cities and distances in the following format:
Alaska Mileage Chart,Anchorage,Anderson,Cantwell,
Anchorage,0,284,210,
Anderson,284,0,74,
Cantwell,210,74,0,
So the algorithm works and outputs the cities in the order they should be visited following the shortest path using the nearest neighbor algorithm always starting with Anchorage as the city of origin or starting city.
Using this data, the example output for the algorithm is: 1,3,2. I have ran this with a 27 element chart and had good results as well. I am using this small one for writing and debugging purposes.
Ideally the output I am looking for is the Name of the City and a cumulative milage.
Right now I am having working on trying to get the cities into an array that I can print out. Help with both parts would be appreciated or help keeping in mind that is the end goal is appreciated as well.
My thought was that ultimately I may want to create an array of {string, int}
so my output would look something like this..
Anchorage 0
Cantwell 210
Anderson 284
I am able to set the first element of the array to 1, but can not get the 2nd and 3rd element of the new output array to correct
This is the code I am having a problem with:
public class TSPNearestNeighbor {
private int numberOfNodes;
private Stack<Integer> stack;
public TSPNearestNeighbor()
{
stack = new Stack<>();
}
public void tsp(int adjacencyMatrix[][])
{
numberOfNodes = adjacencyMatrix[1].length;
// System.out.print(numberOfNodes);
// System.out.print(Arrays.deepToString(adjacencyMatrix));
int[] visited = new int[numberOfNodes];
// System.out.print(Arrays.toString(visited));
visited[1] = 1;
// System.out.print(Arrays.toString(visited));
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\n");
//System.arraycopy(arr_cities, 0, arr_final, 0, 1); // Copies Anchorage to Pos 1 always
//System.out.print(Arrays.deepToString(arr_final)+ "\n");
while (!stack.isEmpty())
{
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes-1)
{
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0)
{
if (min > adjacencyMatrix[element][i])
{
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag)
{
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\n");
minFlag = false;
continue;
}
stack.pop();
}
}
Given the existing structure you are using, you can output the cities in the path using:
public void printCities(Stack<Integer> path, int[][] distances, List<String> names) {
int cumulativeDistance = 0;
int previous = -1;
for (int city: path) {
if (previous != -1)
cumulativeDistance += distances[previous][city];
System.out.println(names.get(city) + " " + cumulativeDistance);
previous = city;
}
}
I'd like to answer your question slightly indirectly. You are making life hard for yourself by using arrays of objects. They make the code difficult to read and are hard to access. Things would become easier if you create a City class with appropriate methods to help you with the output.
For example:
class City {
private final String name;
private final Map<City,Integer> connections = new HashMap<>();
public static addConnection(City from, City to, int distance) {
from.connections.put(to, distance);
to.connections.put(from, distance);
}
public int getDistanceTo(City other) {
if (connections.containsKey(other))
return connections.get(other);
else
throw new IllegalArgumentException("Non connection error");
}
}
I've left out constructor, getters, setters for clarity.
Now outputting your path becomes quite a bit simpler:
public void outputPath(List<City> cities) {
int cumulativeDistance = 0;
City previous = null;
for (City current: cities) {
if (previous != null)
cumulativeDistance += previous.getDistanceTo(current);
System.out.println(current.getName + " " + cumulativeDistance);
previous = current;
}
}
I have two arraylists say
ArrayList<BaseItem> normal;
ArrayList<BaseItem> highlighted;
normal = new ArrayList<BaseItem>();
highlighted = new ArrayList<BaseItem>();
what I am doing is I am Iterating through a 3rd list(called MyItems) and adding the items in it called highlight and normal to the above two lists like this.
for (Iterator<BaseItem> iterator = MyItems.iterator(); iterator.hasNext();) {
BaseItem itemtype = iterator.next();
if (itemtype.isHighlight()) {
highlighted.add(itemtype);
}
else{
normal.add(itemtype);
}
}
So my question is I want to add every 5th and 6th item of the highlited list to the list called normal .i.e elements like 5,6,11,12,17,18 and so on
and also I want to add every 6th and 7th item of normal list to highlighted list i.e 6,7,13,14 and so on.
so now my highlighted and normal lists will contain the items like this
Highlighted -> highlighted1,highlighted2,highlighted3,highlighted4,normal6,normal7 highlighted7,highlighted8.highlighted9,highlighted10,normal13,normal14 and so on
Normal -> Noraml1,normal2,normal3,normal4,normal5,highlighted5,highlighted6,normal7,normal8,normal9,normal10,normal11,normal12,highlighted11,highlighted12 and so on
Any help is always appreciated,
Thanks
If I understand, use a counter when after 5 and 6 insert in your list, add in normal list instead of highlighted list
Try this:
int highAdded = 0;
int normalAdded = 0;
for (Iterator<BaseItem> iterator = MyItems.iterator(); iterator.hasNext();) {
BaseItem itemtype = iterator.next();
if (itemtype.isHighlight()) {
highAdded++;
if (highAdded == 5) {
normal.add(itemtype);
} else if (highAdded == 6) {
normal.add(itemtype);
highAdded = 0;
} else {
highlighted.add(itemtype);
}
}
else{
normalAdded++;
if (normalAdded == 6) {
highlighted.add(itemtype);
} else if (normalAdded == 7) {
highlighted.add(itemtype);
normalAdded = 0;
} else {
normal.add(itemtype);
}
}
}
EDIT
I write this code:
public class StackOverFlowSample {
public static void main(String [] args) {
List<String> lst = new ArrayList<String>();
List<String> lstHigh = new ArrayList<String>();
List<String> lstNormal = new ArrayList<String>();
lst.add("highlighted01");
lst.add("highlighted02");
lst.add("highlighted03");
lst.add("highlighted04");
lst.add("highlighted05");
lst.add("highlighted06");
lst.add("highlighted07");
lst.add("highlighted08");
lst.add("highlighted09");
lst.add("highlighted10");
lst.add("highlighted11");
lst.add("highlighted12");
lst.add("highlighted13");
lst.add("highlighted14");
lst.add("highlighted15");
lst.add("highlighted16");
lst.add("normal01");
lst.add("normal02");
lst.add("normal03");
lst.add("normal04");
lst.add("normal05");
lst.add("normal06");
lst.add("normal07");
lst.add("normal08");
lst.add("normal09");
lst.add("normal10");
lst.add("normal11");
lst.add("normal12");
lst.add("normal13");
lst.add("normal14");
lst.add("normal15");
lst.add("normal16");
int highAdded = 0;
int normalAdded = 0;
for (Iterator<String> iterator = lst.iterator(); iterator.hasNext();) {
String itemtype = iterator.next();
if (itemtype.startsWith("highlighted")) {
highAdded++;
if (highAdded == 5) {
lstNormal.add(itemtype);
} else if (highAdded == 6) {
lstNormal.add(itemtype);
highAdded = 0;
} else {
lstHigh.add(itemtype);
}
}
else{
normalAdded++;
if (normalAdded == 6) {
lstHigh.add(itemtype);
} else if (normalAdded == 7) {
lstHigh.add(itemtype);
normalAdded = 0;
} else {
lstNormal.add(itemtype);
}
}
}
String result = "HIGHLIGHTED ARRAY: ";
for (String curr : lstHigh) {
result += curr + ", ";
}
System.out.print(result);
result = "NORMAL ARRAY: ";
for (String curr : lstNormal) {
result += curr + ", ";
}
System.out.print(result);
}
}
The output is:
HIGHLIGHTED ARRAY: highlighted01, highlighted02, highlighted03, highlighted04, highlighted07, highlighted08, highlighted09, highlighted10, highlighted13, highlighted14, highlighted15, highlighted16, normal06, normal07, normal13, normal14,
NORMAL ARRAY: highlighted05, highlighted06, highlighted11, highlighted12, normal01, normal02, normal03, normal04, normal05, normal08, normal09, normal10, normal11, normal12, normal15, normal16,
Tell me if it's OK ;)
I'm using an ArrayList to hold a history of objects. Each new object I add using the .add method, like:
if(event.getAction() == MotionEvent.ACTION_UP)
{
if(currentWord != null)
{
wordHist.add(currentWord);
}
if(wordHist.size() > WORDHIST_MAX_COUNT)
{
wordHist.remove(0);
}
}
However I don't want this to grow indefinitely, but to be limited to a certain value. If it reaches this maximum value, I want the oldest object (index 0) to be removed, and the rest to be left shifted, so previous index 1 is now index 0, etc.
How can this be done?
Thanks
ArrayList is not really a good choice in this case, but it can by done by calling remove(0) method. But if you want to do that efficiently, a linked list is better
(edited to make it clear that LinkedList is not generally better than ArrayList, but only in this case)
If it reaches this maximum value, I want the oldest object (index 0) to be removed
Then do wordHist.remove(0). That will remove the element at index 0.
To be precise:
wordHist.add(new Word("hello"));
if (wordHist.size() > MAX_SIZE)
wordHist.remove(0);
As user658991 states however, you should be aware of that this is a linear operation, i.e., takes time proportional to the number of elements in the list.
You could do this in constant time using LinkedList methods add and removeFirst.
Another option would be to wrap an array, or ArrayList in a class called something like CircularArrayList. In circular list structures you'll override the oldest element when adding a new one.
Edit:
Your code works fine:
import java.util.*;
class Test {
static int WORDHIST_MAX_COUNT = 3;
static List<String> wordHist = new ArrayList<String>();
public static void add(String currentWord) {
// VERBATIM COPY OF YOUR CODE
if (true/*event.getAction() == MotionEvent.ACTION_UP*/)
{
if(currentWord != null)
{
wordHist.add(currentWord);
}
if(wordHist.size() > WORDHIST_MAX_COUNT)
{
wordHist.remove(0);
}
}
}
public static void main(String[] args) {
add("a");
add("b");
add("c");
for (int i = 0; i < wordHist.size(); i++)
System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
System.out.println();
add("d");
for (int i = 0; i < wordHist.size(); i++)
System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
}
}
Prints:
i: 0, word: a
i: 1, word: b
i: 2, word: c
i: 0, word: b <-- b is now at index 0.
i: 1, word: c
i: 2, word: d
Use the remove( ) method.
Using remove(0) will remove the element from the 0th index.
U can use list.remove(index)// here index being '0', this internally shifts rest of the array up. An alternative solution wud be to use a queue or dequeue.
One simple implementation of what Op De Cirkel suggested
import java.util.ArrayList;
import java.util.List;
public class SimpleCircularHistory {
private int sizeLimit, start = 0, end = 0;
boolean empty = false;
private List<String> history;
public SimpleCircularHistory(int sizeLimit) {
this.sizeLimit = sizeLimit;
history = new ArrayList<String>(sizeLimit);
}
public void add(String state){
empty = false;
end = (end + 1) % sizeLimit;
if(history.size() < sizeLimit){
history.add(state);
}else {
history.set(end, state);
start = (end + 1) % sizeLimit;
}
}
public String rollBack(){
if(empty){ // Empty
return null;
}else {
String state = history.get(end);
if(start == end){
empty = true;
}else {
end = (end + sizeLimit - 1) % sizeLimit;
}
return state;
}
}
public void print(){
if(empty){
System.out.println("Empty");
}else {
for(int i = start;; i = (i + 1) % sizeLimit){
System.out.println(history.get(i));
if(i == end) break;
}
System.out.println();
}
}
public static void main(String[] args) {
SimpleCircularHistory h = new SimpleCircularHistory(3);
h.add("a");
h.add("b");
h.add("c");
h.add("d");
h.add("e");
h.add("f");
h.print();
h.add("X");
h.add("Y");
h.rollBack();
h.rollBack();
h.print();
h.add("t");
h.add("v");
h.add("w");
h.print();
h.rollBack();
h.rollBack();
h.rollBack();
h.print();
h.rollBack();
h.print();
}
}
This would print out :
d
e
f
f
t
v
w
Empty
Empty
Yeah, I've noticed this behaviour in adroid's lists too. It's REALLY irritating.
Anyway, there is a way to get around it if I don't mind object creation/destruction and the resulting garbage collection (NEVER do this in a onDraw of a surfaceview or something).
What I do is basically have two tracking int's; one to place the new object, and one to remove it:
int trackInt = 0;
int removeInt = 0;
//and then, in the method/class you use this:
Object newobject = new Object();
//add to list
objectList.add(trackInt, newobject);
trackInt++;
if (bugList.size() > 20) //20 is the max number of object you want, ie the maximum size of the list
{
objectList.remove(removeInt);
trackInt = removeInt;
removeInt++;
if (removeInt > 19) //remember, the list is zero indexed!
{
removeInt = 0;
}
}
Commons-collections has exactly what you're looking for:
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/buffer/CircularFifoBuffer.html