Incrementing different variables on different conditions - java

I have multiple int type variables and on specific condition any one of those variables got incremented. Now I have to know some data structure in java that i can do this thing without using multiple variables.
A portion of my code is here:
switch(diff)
{
case 4:
{
count4++;
break;
}
case 5:
{
count5++;
break;
}
case 6:
{
count6++;
break;
}
}
Conditions may be increased so it is not good approach to add variable for each new condition. Kindly let me know some other better approach or data structure which can solve my problem.
Edit 1:
I am extracting time difference between consucetive lines in log file. Actually in the end I need a summary like
Difference 3 sec = 10
Difference 4 sec = 5
For above purpose I am using counter variables for each time difference. I need to know about some other way to do this thing,

You could use a Map (e.g. HashMap) with the key representing the name of the variable and the map's value representing the variable's value. This allows for having a flexible data structure where it is not necessary to know in before how many "variables" there will be.

This is strange because of the names you gave to your variables, but you could use an array:
int[] counts = {0, 0, 0};
Then count4 is counts[0], count5 is counts[1] and count6 is counts[2] so you can do:
counts[diff - 4]++;

You can use a HashMap
Example:
public class Test
{
public static void main(String[] args)
{
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("counter5", 1);
map.put("counter4", 1);
map.put("counter2", 1);
map.put("counter1", 1);
int diff = 2;
compute(map, diff);
diff = 2;
compute(map, diff);
diff = 1;
compute(map, diff);
}
private static void compute(HashMap<String, Integer> map, int diff)
{
System.out.println("Before counter no: "+diff+" value "+map.get("counter" + diff));
Integer counter = map.get("counter" + diff);
map.put("counter" + diff, --counter);
System.out.println("After counter no: "+diff+" value "+map.get("counter" + diff));
System.out.println("");
}
}

As pzaenger you can do something like:
As you already know how many case are there so you can initialize an array with that much size. Like you have 10 case then you can initialize an int array of size 10 as:
int[] count = new int[10];
now suppose you have a case of 4, i.e. 4th index of int array but as index start from 0 so you can do
int[4-1] = int[4-1]++;

if you just want to keep track of the diff number you could do something like this.
Map<Integer, Integer> pathMap = new HashMap<Integer, Integer>();
public void testSaveEntries() {
for ( int i = 0; i < 10; i++) {
int value = i % 5;
increaseCounter(value);
}
}
private void increaseCounter(int i) {
Integer value = pathMap.get(i);
pathMap.put(i, value == null ? 1 : ++value);
}

Try This....
public static void main(String[] args) {
int[] aaa=new int[]{10,2,4,5,7,8,3,34,4,4,545,5,3,4,4,5,5,5,10,3,4,45,6,2,7};
Map<Integer, Integer> all_counts=new LinkedHashMap<Integer,Integer>();
for (int key : aaa) {
if(all_counts.containsKey(key))
{
Integer count=all_counts.get(key);
count++;
all_counts.put(key, count);
}
else
{
all_counts.put(key, 1);
}
}
for (Map.Entry<Integer, Integer> entry : all_counts.entrySet())
{
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}

Related

How to print the sum of values from the same objects of 2 parameter in array

I am learning java and I hit into a snag as I could not figure out my loop or array.
I have an array which contains class objects containing a string and integer parameters, in my code, it will be name and dollars.
I am trying to print out the array in which, if there is a same name, it is to print once and with the sum of the dollars (from the same name).
In my Dollars.java
public class Dollars
{
private String name;
private int dollars;
public dollars (String name, int dollars)
{
this.name = name;
this.dollars = dollars;
}
public String getName()
{
return name;
}
public int getChange()
{
return dollars;
}
}
In my main file/ TestDollars.java
public class TestDollars
{
public static void displayArray(Dollars[] dol)
{
int sum = 0;
for (int n=0; n<dol.length; n++)
{
for (int m=n+1; m<dol.length; m++)
{
if (dol[n].getName().equals(dol[m].getName()))
{
// System.out.printf("%s -- %d\n", dol[n].getName(), dol[n].getChange());
sum = dol[n].getChange() + dol[m].getChange();
System.out.printf("%s -- %d\n", dol[m].getName(), sum);
break;
}
}
System.out.printf("%s -- %d\n", dol[n].getName(), dol[n].getChange());
}
}
public static void main(String[] args)
{
// Test with 5 records
Dollars[] dollarsArr = new Dollars[5];
dollarsArr[0] = new Dollars("john", 10);
dollarsArr[1] = new Dollars("peter", 12);
dollarsArr[2] = new Dollars("sam", 5);
dollarsArr[3] = new Dollars("alvin", 16);
dollarsArr[4] = new Dollars("peter", 30);
displayArray(dollarsArr);
}
}
Irregardless where I place my print statement in the displayArray, the record 'peter' will gets printed twice.
Expected output:
john -- 10
peter -- 42
sam -- 5
alvin -- 16
Current output:
john -- 10
peter -- 42
peter -- 12
sam -- 5
alvin -- 16
peter -- 30
You want to group your list by name, please use JAVA 8+ API Stream and the collector group by
public static void displayArray(Dollars[] dol)
{
Stream.of(dol)
// Group by name
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// Collect a map name and calculate the sum
.collect(
Collectors.toMap(x -> {
int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(),total);
}, Map.Entry::getValue))
// Print
.forEach((dollarsTotal, vals) -> {
System.out.println(dollarsTotal.getName()+ " -- "+ dollarsTotal.getChange());
// Bonus : Display transactions :
for(Dollars transaction : vals)
{
System.out.println(" \t "+transaction.getName() + " add -- " + transaction.getChange());
}
});
}
If you want only the values you can collect the keyset
Set<Dollars> groupedByName = Stream.of(dol)
// Group by name
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// Collect a map name and calculate the sum
.collect(
Collectors.toMap(x -> {
int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(),total);
}, Map.Entry::getValue)).keySet();
The other answer guides you on fixing your code (Buy they require more work to avoid double counting).
You can reduce the time complexity from O(n2) to O(n) (and make it simpler) by having a data structure (like a map) to aggregate the result.
Let us create a Map<String, Integer> to map a name to the total dollars for that name.
Map<String, Integer> result = new HashMap<>();
for (int i = 0; i < dol.length; i++) {
if (!result.containsKey(dol[i].getName())) { //first time you encounter a name
result.put(dol[i].getName(), dol[i].getChange());
} else {
//add the current change to the already existing sum
int sumSoFar= result.get(dol[i].getName());
result.put(dol[i].getName(), sumSoFar + dol[i].getChange());
}
}
System.out.println(result);
Result is,
{peter=42, alvin=16, john=10, sam=5}
You can simplify the above code using Map's merge method as:
for (Dollars dollars : dol) {
result.merge(dollars.getName(), dollars.getChange(), Integer::sum);
}
The third argument is a BiFunction which sums up the old value and new value (the sum accumulated so far and the current change value). When written as a lambda expression, Integer::sum can be written as (sumSoFar, currentChange) -> sumSoFar + currentChange.
A stream evangelist way would be to use Collectors.groupingBy and Collectors.summingInt.
Arrays.stream(dol)
.collect(Collectors.groupingBy(Dollars::getName, Collectors.summingInt(Dollars::getChange)));
While navigating the array, assign the change of each non-null array-element to a variable e.g. sum and then add the change of the succeeding duplicate elements to it. Make sure to assign null to the indices where duplicate elements are found so that they can not be counted again. It also means that you will have to perform a null check before performing any operation on the array elements. Print the value of sum once you have checked the complete array for duplicate elements.
public static void displayArray(Dollars[] dol) {
for (int n = 0; n < dol.length; n++) {
if (dol[n] != null) {
int sum = dol[n].getChange();
for (int m = n + 1; m < dol.length; m++) {
if (dol[m] != null && dol[n].getName().equals(dol[m].getName())) {
sum += dol[m].getChange();
dol[m] = null;
}
}
System.out.printf("%s -- %d\n", dol[n].getName(), sum);
}
}
}
Output:
john -- 10
peter -- 42
sam -- 5
alvin -- 16
Note: If you want to keep the original array intact, pass the clone of the array to the method, displayArray instead of passing the array itself as shown below:
displayArray(dollarsArr.clone());

How would you update the values in a hashmap based on prior conditions?

Something fundamental about hashmaps and for loops is hard for me to grasp here. What I'm trying to do is add +1 to the value associated with the key based on the Keys method every time the value within the array list is associated with the key string.
So if there are 3 values in the array list that are positive then the hashmap should have the value with the key "positive" updated to 3.
Any help/advice would be appreciated - thank you.
public String Keys(double input){
if (input > 0){
System.out.println("positive");
}
else if (input < 0) {
System.out.println("negative");
}
else if (input == 0) {
System.out.println("zero");
}
return "";
}
public HashMap<String, Integer> increaseValues(ArrayList<Double> inputs){
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("positive", 0);
hashMap.put("negative", 0);
hashMap.put("zero", 0);
//What I tried before adding the Keys method.
//This updates the value but the loop won't continue if another input in the
//arraylist is true.
for (int i = 0; i < inputs.size(); i++){
double input = inputs.get(i);
if (input > 0){
hashMap.put("positive", 1);
} else if (input < 0){
hashMap.put("negative", 1);
} else if (input == 0){
hashMap.put("zero", 1); }
return hashMap;
}
public void main(String[] args){
ArrayList<Double> inputs = new ArrayList<>();
inputs.add(-4.56);
inputs.add(-4.66);
inputs.add(0.0);
inputs.add(6.0);
inputs.add(-6.99);
inputs.add(6.97);
}
Map.put(k, v) always overrides your previous value. You can use the "traditional approach":
if (!map.containsKey("positive"))
map.put("positive", 0);
map.put("positive", map.get("positive") + 1);
or better use the new merge funtction that is added for exactly such cases:
map.merge("positive", 1, (prev, one) -> prev + one);
But this whole logic can be greatly shortened by using Math.signum() and stream collectors:
Map<Double, Long> collect = inputs.stream()
.collect(Collectors.groupingBy(Math::signum,
Collectors.counting()));
System.out.println("positive: " + collect.get(1.0));
System.out.println("negative: " + collect.get(-1.0));
System.out.println("zero: " + collect.get(0.0));
Lets start with a quick tidy, lets create an enum and remove those nasty String constants that you don't have defined anywhere:
public enum Sign {
POSITIVE,
ZERO,
NEGATIVE;
public static Sign of(double d) {
if (d > 0) {
return POSITIVE;
}
if (d < 0) {
return NEGATIVE;
}
return ZERO;
}
}
Now we can trivially write a method to increment the appropriate value:
public void increment(final double d, final Map<Sign, Integer> count) {
count.merge(Sign.of(d), 1, Integer::sum);
}
For a quick test:
final Map<Sign, Integer> count = new EnumMap<>(Sign.class);
increment(0, count);
System.out.println(count);
increment(-1, count);
System.out.println(count);
increment(1, count);
System.out.println(count);
increment(-2, count);
System.out.println(count);
increment(2, count);
System.out.println(count);
Output:
{ZERO=1}
{NEGATIVE=1, ZERO=1}
{POSITIVE=1, NEGATIVE=1, ZERO=1}
{POSITIVE=1, NEGATIVE=2, ZERO=1}
{POSITIVE=2, NEGATIVE=2, ZERO=1}
So how does this magic work? From the documentation for Map.merge
If the specified key is not already associated with a value or is
associated with null, associates it with the given non-null value.
Otherwise, replaces the associated value with the results of the given
remapping function, or removes if the result is null. This method may
be of use when combining multiple mapped values for a key.
So it takes the key as the first argument to merge - in the case Sign.of(d); this selects the correct bucket. If the value mapped to that key is null then it simply puts a mapping for the key to the value passed as the second argument - in this case 1. Otherwise it gets a litte more complicated; it takes the value currently mapped to that key and uses the remappingFunction passed as the third argument. This is a BiFunction<V,V,V>, so it takes two arguments of type V, the value type and returns a single one - it merges the two together. Here we use Integer::sum to take the existing value, the new value and return their sum.
But we can go one step further, we can use a Stream to carry this out on an arbitrary double[]:
public Map<Sign, Long> count(final double[] d) {
return Arrays.stream(d)
.mapToObj(Sign::of)
.collect(groupingBy(identity(), () -> new EnumMap<>(Sign.class), counting()));
}
Note: I've used an EnumMap here, which is Map optimised for using an enum as the key.
You can solve it pretty concisely with streams. You need a function which turns value into the negative/zero/positive key. Then just group by this key with a counting collector. It's basically a two-liner:
List<Double> values = Arrays.asList(-4.56,-4.66,0.0, 6.0, -6.99, 6.97);
Function<Double, String> toKey = v -> v < 0 ? "negative" : (v == 0 ? "zero" : "positive");
Map<String, Long> result = values
.stream()
.collect(Collectors
.groupingBy(
toKey,
Collectors.counting()));
The method put of HashMap maps unique keys with values. It replaces the existing value with the new value in case the provided key is already present in the map.
You need to define a method similar to below.
public void addValueToList(Double d, List<Double> inputs , Map<String,Integer> map){
if( d == null ) return;
if ( isZero(d) ){
Integer count = map.get("zero");
if(count == null){
count = 1;
}else {
count ++;
}
map.put("zero",count);
}else if( isNegative(d) ) {
Integer count = map.get("negative");
if(count == null){
count = 1;
}else {
count ++;
}
map.put("negative",count);
}else {
Integer count = map.get("positive");
if(count == null){
count = 1;
}else {
count ++;
}
map.put("positive",count);
}
inputs.add(d);
}
For writing method for comparing the value you can refer https://stackoverflow.com/a/10400718/504133

How to compare elements of a list with elements of a map in Java?

I have the following code (with some sample data), and wished to check whether there is any better or performant way to compare each element of the list of map to the subsequent one:
import java.util.*;
public class CompareElements {
private static List<Map<String, String>> sample = new ArrayList<>(0);
private static int MIN = 0;
private static int MAX = 10;
static {
populateListOfMaps();
}
/*
* This is the main part of the question, rest is just to generate test data..
*/
public static void main(String[] args){
// Can we simplify this part using lambda's or any library?
for (int i = 0; i < sample.size() -1; i++) {
for (int j = i+1; j < sample.size(); j++) {
Map<String, String> referenceMap = sample.get(i);
Map<String, String> candideMap = sample.get(j);
if(referenceMap.get("key").equalsIgnoreCase(candideMap.get("key"))){
System.out.println("Equal : " + i + " || " + referenceMap.get("key") + " and "+ j + " || " + candideMap.get("key") + " are pairs");
} else {
System.out.println("Not equal : " + i + " || " + referenceMap.get("key") + " and "+ j + " || " + candideMap.get("key") + " are pairs");
}
}
}
}
private static void populateListOfMaps(){
if(sample.size() <= 10){
Map<String, String> someMap = new HashMap<>(0);
someMap.put("key", "value" + randInt(MIN, MAX));
sample.add(someMap);
populateListOfMaps();
}
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
My requirement is to compare each element of the list of maps and then check for equality to remove duplicate, this is a simpler part, but each map in my real time application has 2 keys-values (but both are String.. no custom POJO object).
The above code works but I wish to make this more concise and performant code.
Can we use lambdas or streams?
As you are getting data from MongoDB, I assume you have no control over the schema, so using a POJO isn't a simple option. (it can be done with generated code, but you probably don't want to go there)
What you can do is using groupingBy to change this O(n^2) loops into O(n)
public static void main(String... args) {
List<Map<String, String>> sample = populateListOfMaps();
sample.stream()
.collect(Collectors.groupingBy(m -> m.get("key")))
.forEach((key, list) -> System.out.println(key + " : " + list));
}
private static List<Map<String, String>> populateListOfMaps() {
Random rand = new Random();
return IntStream.range(0, 10)
.mapToObj(i -> {
Map<String, String> someMap = new HashMap<>(2);
someMap.put("key", "value-" + rand.nextInt(10));
return someMap;
})
.collect(Collectors.toList());
}
This will print all the entries which have the same "key" value with O(n) time complexity. e.g.
value-9 : [{key=value-9}]
value-8 : [{key=value-8}, {key=value-8}, {key=value-8}]
value-5 : [{key=value-5}]
value-7 : [{key=value-7}, {key=value-7}]
value-1 : [{key=value-1}]
value-0 : [{key=value-0}]
value-2 : [{key=value-2}]
I'm not realy sure what your exact requirements are so to tackle your question one part at a time:
check whether there is any better or performant way to compare each element of the list of map to the subsequent one:
How about using keySets?
Set<String> s1 = new HashSet< String >(referenceMap.values());
Set<String> s2 = new HashSet< String >(candideMap.values());
// Get intersection of values
s1.retainAll(s2);
// You can also get corresponding keys for each value later
This should reduce your complexity from O(n^2) to O(n)
each map in my real time application has 2 keys-values (but both are String.. no custom POJO object).
Not sure what you mean by real-time. Are the maps changing in real time? Neither your solution nor mine would be thread safe.
Do you mean 2 keys-values for each entry? If you mean 2 values for each key, you would probably override the hashcode(), equals() and your code should work.
Let me know if I misunderstood your question

Is performance gained when using continue in a for-loop with many if-statements?

I have a for loop in a java program which iterates through a set of maps.
Inside the loop I have around 10 different if-statements which checks the name of each key inside the each map.
Example:
for (<String, Object> map : object.entrySet()) {
if (map.getKey().equals.("something") {
do_something;
continue;
}
if (map.getKey().equals.("something_else") {
do_something_else;
continue;
}
if ...
}
Do I gain any performance when adding continue-statements like this?
When I step through my code in my IDE and NOT have these continue statements, each if-statement will be tested even if the first one matches.
If I have them like this and the first if matches, the for loop will skip the next 9 if-statements and continue with the next object.
Maybe the compiled code will treat it differently and the added continue-statements actually makes the loop slower?
Instead of using continue all the time, do the getKey() just once and use else if:
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if (key.equals("something")) {
// ...
} else if (key.equals("something else")) {
// ...
}
}
Or use a switch statement:
for (Map.Entry<String, Object> entry : map.entrySet()) {
switch (entry.getKey()) {
case "something":
// ...
break;
case "something else":
// ...
break;
}
If you want the current iteration to end after the first condition evaluates to true, you should use if-else-if-...-else. In my opinion, that's more clear than using continue, since that's what this syntax exists for.
for (<String, Object> map : object.entrySet()) {
if (map.getKey().equals.("something") {
do_something;
}
else if (map.getKey().equals.("something_else") {
do_something_else;
}
else if (...) {
...
}
... else {
...
}
}
With your current implementation, yes you are gaining a performance boost by skipping the remaining if statements using the continue keyword, although with only a constant of ten "if" statements, it's not that bad (10n = O(n) time). Having said that, the more practical way to approach this, as Eran stated, is to make use of else if statements, which will achieve the same result that you are currently using.
Because you have just a few values, IMO, you'll have a real performance improvement here if you map your strings to ints, since the int comparison is far faster than a String comparison.
Check this out
public class Lab1 {
public static void main(String[] args) {
usingStrings();
usingInts();
}
private static void usingInts() {
int[] samples = new int[100000000];
int[] values = {1,2,3,4};
for(int i=0;i<samples.length-1;i++) {
samples[i] = values[(int)(Math.random()*values.length)];
}
int total = 0;
long ini = System.currentTimeMillis();
for(int i=0;i<samples.length-1;i++) {
if (1 == (samples[i])) {
total+=doSomeJob();
}else if (2 == (samples[i])) {
total+=doSomeJob();
}else if (3 == (samples[i])) {
total+=doSomeJob();
}else {
total+=doSomeJob();
}
}
long end = System.currentTimeMillis();
System.out.println("Ints="+(end-ini));
}
private static void usingStrings() {
String[] samples = new String[100000000];
String[] values = {"one mule","two mules","three mules","four mules"};
for(int i=0;i<samples.length-1;i++) {
samples[i] = values[(int)(Math.random()*values.length)];
}
int total = 0;
long ini = System.currentTimeMillis();
for(int i=0;i<samples.length-1;i++) {
if ("one mule".equals(samples[i])) {
total+=doSomeJob();
}else if ("two mules".equals(samples[i])) {
total+=doSomeJob();
}else if ("three mules".equals(samples[i])) {
total+=doSomeJob();
}else {
total+=doSomeJob();
}
}
long end = System.currentTimeMillis();
System.out.println("Strings="+(end-ini));
}
/**
*
*/
private static int doSomeJob() {
int c = 0;
for(int i=0;i<1000;i++) {
c++;
}
return c;
}
}
output
Strings=962
Ints=6
which is actually how DBMS indexes work behind the scenes

How to leftshift an ArrayList

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

Categories

Resources