I am adding data into HashMap where node is an object with variables index and successor.
private static HashMap <Integer, node> peerList = new HashMap<Integer, node>();
public void generateFingerTable (int node_position) {
chordSize = chord.initChordSize;
chord chord = new chord();
//create new node and add to map
node newPeer = new node();
peerList.put(node_position, newPeer);
for (int i=0; i<chordSize; i++) {
int temp = i+1;
newPeer.index = new int [chordSize];
newPeer.successor = new int [chordSize];
int temp1 = node_position + (int)Math.pow(2, temp-1) % chord.getChordSize();
peerList.get(node_position).index[i] = temp;
peerList.get(node_position).successor[i] = temp1;
System.out.println ("Index: " + newPeer.index[i] + "\n" + "Successor: " +
newPeer.successor[i]);
}
}
public void printFingerTable() {
for (Map.Entry<Integer, node> m : peerList.entrySet()) {
System.out.println ("Peer " + m.getKey() + " with Index: " + m.getValue().getIndex() + " Successor: " +
m.getValue().getSuccessor());
}
When I print the Hash details, the result shows Index: [0,0,0,0,5] , Successor:[0,0,0,0,16] which means the previously added elements gets replaced and only the last element is saved in Hashmap.
The intended result should be Index [1,2,3,4,5], Successor: [1,2,4,8,16].
How can I amend this so the data don't get replaced?
You initialize the index and successor arrays in each iteration of the loop, so only the value of the last index remains in the end, and the others are 0.
You should initialize the arrays before the loop.
Change the code to :
public void generateFingerTable (int node_position) {
chordSize = chord.initChordSize;
chord chord = new chord();
//create new node and add to map
node newPeer = new node();
peerList.put(node_position, newPeer);
newPeer.index = new int [chordSize];
newPeer.successor = new int [chordSize];
for (int i=0; i<chordSize; i++) {
int temp = i+1;
int temp1 = node_position + (int)Math.pow(2, temp-1) % chord.getChordSize();
peerList.get(node_position).index[i] = temp;
peerList.get(node_position).successor[i] = temp1;
System.out.println ("Index: " + newPeer.index[i] + "\n" + "Successor: " +
newPeer.successor[i]);
}
}
I think you should use a different data-type or structure than HashMap as HashMaps do not guarantee order. I am pointing this out as your code peerList.put(node_position, newPeer); seems to imply you are setting the position of your object in your HashMap but that is not the case. I only say this because you are just using the variable called node_postion to key or hash where your data object will live in your HashMap. See this link for more details.
Difference between HashMap, LinkedHashMap and TreeMap
Related
I am trying to find the COUNT of repeated elements in an array list.
for example if array named "answerSheerPacketList" list contains values like {20,20,30,40,40,20,20,20},i need to show output like {20=2,30=1,40=2,20=3}.
Map<String, Integer> hm = new HashMap<String, Integer>();
for (String a : answerSheerPacketList) {
Integer j = hm.getinsAnswerSheetId(a);
hm.put(a, (j == null) ? 1 : j + 1);
}
// displaying the occurrence of elements in the arraylist
for(Map.Entry<String, Integer> val : hm.entrySet()){
System.out.println("Element " + val.getKey() + " "
"occurs" + ": " + val.getValue()+ " times");
}
when i executed above code i got output like {20=5,30=1,40=2} but i am trying to get a output like {20=2,30=1,40=2,20=3}.
A simple approach here would be to just iterate the arraylist once, and then keep tallies as we go along:
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(20);
list.add(30);
list.add(40);
list.add(40);
list.add(20);
list.add(20);
list.add(20);
Integer curr = null;
int count = 0;
System.out.print("{");
for (int val : list) {
if (curr == null) {
curr = val;
count = 1;
}
else if (curr != val) {
System.out.print("(" + curr + ", " + count + ")");
curr = val;
count = 1;
}
else {
++count;
}
}
System.out.print("(" + curr + ", " + count + ")");
System.out.print("}");
{(20, 2)(30, 1)(40, 2)(20, 3)}
This is a classic problem of counting runs of consecutive elements in an array. I have renamed the array to arr in the code for brevity.
int run = 1;
for (int i = 0; i < n; ++i) { // n is the size of array
if (i + 1 < n && arr[i] == arr[i + 1]) {
run++; // increment run if consecutive elements are equal
} else {
System.out.println(arr[i] + "=" + run + ", ");
run = 1; // reset run if they are not equal
}
}
Performance-wise, this approach is aysmptotically optimal and runs in O(n), where n is the number of elements in the array.
Set<Integer> distinctSet = new HashSet<>(answerSheerPacketList);
HashSet<Integer,Integer> elementCountSet=new HashSet<>();
for (Integer element: distinctSet) {
elementCountSet.put(element,Collections.frequency(answerSheerPacketList, element));
}
What you need is basically frequency counting. The following code will do it with a single pass through your answerSheerPacketList array:
int[] answerSheerPacketList = // initialization
Map<Integer, Integer> frequencyCount = new LinkedHashMap<>();
for (int i : answerSheerPacketList) {
Integer key = Integer.valueOf(i);
if (frequencyCount.containsKey(key)) {
frequencyCount.put(key, Integer.valueOf(frequencyCount.get(key) + 1));
} else {
frequencyCount.put(key, Integer.valueOf(1));
}
}
for (Integer key : frequencyCount.keySet()) {
System.out.println("Element " + key + " occurs: " + frequencyCount.get(key)
+ " times");
}
I have a String array defined and read some values from a table into it:
String[][] ssRet = null;
ssRet = new String[tblRoDe.getNumRows()+1][2];
ssRet[0][0] = "AGR_NAME";
ssRet[0][1] = "TEXT";
for(int j=0; j<tblRoDe.getNumRows(); j++ )
{
tblRoDe.setRow( j );
ssRet[j+1][0] = tblRoDe.getString( "AGR_NAME" );
ssRet[j+1][1] = tblRoDe.getString( "TEXT" );
logger.debug("------- Start Entry #" + (j+1) + " -------");
logger.debug(ssRet[0][0] + ": " + ssRet[j+1][0]);
logger.debug(ssRet[0][1] + ": " + ssRet[j+1][1]);
logger.debug("------- End Entry #" + (j+1) + " -------");
}
My task now is: depending on a function param I will have to read values from a different table into the same string array (append this). There are still only two columns but I have to add more lines.
How can I achieve that?
You will have problems when you stick with arrays, as they are fix in their size.
For a more dynamic solution you will need a Collection, such as List - this grow with the data.
Arrays cannot be expanded once created.
So, there are the following solutions.
Create array of needed size. You can achieve this if you know the array size before reading the data.
create new array once you have to "expand" it and copy data from the small array to the bigger one. Then continue to fill the bigger array. You can use System.arraycopy() or implement the logic yourself
Use any implementation of java.util.List instead of array.
BTW unless this is a school exercise avoid using 2 dimensional array in this case. I'd recommend you to define your custom class with 2 fields name and text and then use 1 dimensional array or list according to your choice.
If you have a different amount of Rows, and you can't excatly say how much rows it will be you should use ArrayList instead of an array with an fixed size. To an ArrayList you can add as muchs values as you want. The Problem is, that an Array, once it is created, cant be resized.
To this List you could save Objects of your own type(to handle your data) like this:
public class TableRow {
private String agr_name;
private String text;
private int entryNr;
public TableRow(String agr_name, String text, int entryNr) {
this.agr_name = agr_name;
this.text = text;
this.entryNr = entryNr;
}
public String getAgr_name() {
return agr_name;
}
public void setAgr_name(String agr_name) {
this.agr_name = agr_name;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getEntryNr() {
return entryNr;
}
public void setEntryNr(int entryNr) {
this.entryNr = entryNr;
}
}
This used to your code should look like that:
ArrayList<TableRow> allRows = new ArrayList<>();
for (int j = 0; j < tblRoDe.getNumRows(); j++) {
tblRoDe.setRow(j);
TableRow trow = new TableRow(tblRoDe.getString("AGR_NAME"), tblRoDe.getString("TEXT"), j);
allRows.add(trow);
logger.debug("------- Start Entry #" + trow.getEntryNr() + " -------");
logger.debug("AGR_Name: " + trow.getAgr_name());
logger.debug("TEXT: " + trow.getText());
logger.debug("------- End Entry #" + trow.getEntryNr() + " -------");
}
Hope that helps!
You can't manipulate the array size after creating it , so Use List as it can grow and it's considered as a dynamic solution
List<List<String>> ssRet = new ArrayList<ArrayList<String>>();
List<String> temp=ArrayList<String>(); //creating temp list
temp.add("AGR_NAME");
temp.add("TEXT");
ssRet.add(temp);
for(int j=0; j<tblRoDe.getNumRows(); j++ )
{
tblRoDe.setRow( j );
temp.clear();//clear list instead of creating new one
temp.add(tblRoDe.getString("AGR_NAME"));
temp.add(tblRoDe.getString("TEXT"));
ssRet.add(temp);
}
To get the data :-
for(int i = 0 ; i < ssRet.size() ; i++){
for(int j = 0 ; j < ssRet.get(i).size() ; j++){
System.out.println("The "+(i+1) + " array data");
System.out.println(ssRet.get(i).get(j));
}
}
// Im trying to find the largest String in my ArrayList and print it out and also to include what index the largest element resides at and to print that to screen too. Im just wondering where Im going wrong.
Thanks.
import java.util.Scanner;
import java.util.ArrayList;
public class ArraylistString
{
public static void main(String [] args)
{
// Instance of Scanner class
Scanner keyboardIn = new Scanner(System.in);
// Declare an array list of Strings
ArrayList<String> Str = new ArrayList<>();
// Add names to ArrayList
Str.add("Jim Bob");
Str.add("Bobby Jones");
Str.add("Rob Stiles");
int largestString = Str.size();
int index = 0;
// Use for loop to print out elements from ArrayList
for(int i = 0; i < Str.size(); i++)
{ // Test which String is the largest
if(Str[i].size() > largestString)
{
largestString = Str[i].size();
index = i;
}
}
// Output largest String and index it was found at
System.out.println("Index " + index + " "+ Str[index] + " " + "is the largest and is size " + largestString);
}
}
You can also use java.util.Collections.max or the Stream version:
Java 8
String max = Collections.max(strings, Comparator.comparing(String::length)); // or s -> s.length()
OR
String max = strings.stream().max(comparing(String::length)).get();
Prior Java 8
String max = Collections.max(Str, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
Then
System.out.println("Index " + arr.indexOf(max) + " " + max + " " + "is the largest and is size " + max.length());
Please try these code . Here i am trying with get() to access the ArrayList elements, which is working correctly.
import java.util.Scanner;
import java.util.ArrayList;
class ArraylistString
{
public static void main(String args[])
{
ArrayList<String> Str = new ArrayList<String>();
Str.add("Jim Bob");
Str.add("Bobby Jones");
Str.add("Rob Stiles");
int largestString = Str.get(0).length();
int index = 0;
for(int i = 0; i < Str.size(); i++)
{
if(Str.get(i).length() > largestString)
{
largestString = Str.get(i).length();
index = i;
}
}
System.out.println("Index " + index + " "+ Str.get(index) + " " + "is the largest and is size " + largestString);
}
}
You have the correct idea, but wrong syntax. In Java, only arrays support the [] syntax. An ArrayList isn't an array, it's a class that implements the List interface, and you should use the get method to access its members. Similarly, a String doesn't have a size() method, it has a length() method.
I would set your largestString variable to your first String that you add:
int largestString = Str.get(0).length();
Then you should use the following to check for the largest String:
if(Str.get(i).length() > largestString) {
largestString = Str.get(i).length();
index = i;
}
You cannot index into an ArrayList with [] as you were trying to do.
I would also suggest better variable names. If I saw Str as a variable I would think it was a String. Maybe try strList or something like that.
From Java-8 and onwards:
List<Integer> numList = Arrays.stream(Str).map(String::length).collect(Collectors.toList());
Integer m = numList.stream().mapToInt(i->i).max().orElse(4000); //get strings with their length
int k = numList.indexOf(m); //index of String with Maximum Length
System.out.println(Str.get(k)); //get your longest string
Using Java 8:
Optional<String> op = Str.stream().sorted((e1,e2)-> e1.length() > e2.length() ? -1 :1).findFirst();
What are you getting as output?
also, the line
int largestString = Str.size()
is setting largestString as the number of elements in the array Str so that may cause errors. I would set it to 0 or even -1 as a baseline, or maybe Str[0].size() so that you can start your for loop with your first element as your baseline.
EDIT:
I didn't even realize this was Java so like what people are saying, you cannot use the [] operator as you can in most languages and you should use string.length() not str.size()
public class HashtableDemo {
static String newLine = System.getProperty("line.separator");
public static void main(String[] args) {
//dictionary can be created using HashTable object
//as dictionary is an abstract class
Hashtable ht = new Hashtable();
//put(key, value)
ht.put("MIKE", 1);
ht.put("CHIN", 2);
ht.put("CHRIS", 3 );
ht.put("HOLY", 4);
//looping through all the elements in hashtable
String str;
//you can retrieve all the keys in hashtable using .keys() method
Enumeration names = ht.keys();
while(names.hasMoreElements()) {
//next element retrieves the next element in the dictionary
str = (String) names.nextElement();
//.get(key) returns the value of the key stored in the hashtable
System.out.println(str + ": " + ht.get(str) + newLine);
}
}
}
How can I add the all the key values into a variable, like 1+2+3+4=10?
Unless you need synchronization, I would recommend using a Map instead of the HashTable. As suggested by the documentation:
If a thread-safe implementation is not needed, it is recommended to
use HashMap in place of Hashtable.
Example:
Map<String, Integer> ht = new HashMap<String, Integer>();
ht.put("MIKE", 1);
ht.put("CHIN", 2);
ht.put("CHRIS", 3 );
ht.put("HOLY", 4);
int total = 0;
for(Integer value: ht.values()){
total+=value;
}
System.out.println(total);
Instead of iterating over the keys, you could simply iterate over the value:
int sum = 0;
for (Integer val : ht.values()) {
sum += val;
}
I'm having a problem with some list manipulation. I take the user's input and search through it: if i find an "=" sign i assume that the string in front of it is the name of a variable , so on the line right above that variable i want to add a new string to the user's input (in this case it is called "tempVAR", doesn't really matter though). I've been trying to do this with StringBuilder but without any success , so i currently am trying to do it with ArrayLists but I am getting stuck at adding new elements to the list. Because of the way list.add(index,string) works , the elements to the right of what i am adding will always add +1 to their index. Is there a way to always know exactly what index i am looking for even after a random number of string has been added? Here is my code so far, if you run it you will see what i mean, instead of "tempVAR" or "tempVar1" being added above the name of the variable they will be added one or to positions in the wrong way.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
public class ToTestStuff {
static List<String> referenceList = new ArrayList<String>();
public static final String SEMICOLUMN = ";";
public static final String BLANK = " ";
public static final String EMPTY = "";
public static final String LEFT_CURLY = "{";
public static final char CARRIAGE_RETURN = '\r';
public static final String CR_STRING = "CARRIAGE_RETURN_AND_NEW_LINE";
public static final char NEW_LINE = '\n';
public static void main(String[] args) {
List<String> test = new ArrayList<String>();
String x = "AGE_X";
String y = "AGE_Y";
String z = "AGE_YEARS";
String t = "P_PERIOD";
String w = "T_VALID";
referenceList.add(x);
referenceList.add(y);
referenceList.add(z);
referenceList.add(t);
referenceList.add(w);
String text2 = " if ( AGE_YEARS > 35 ) {\r\n"
+ " varX = P_PERIOD ;\r\n"
+ " }\r\n"
+ " if ( AGE_YEARS < 35 ) {\r\n"
+ " varY = T_VALID ;\r\n"
+ " varZ = AGE_Y ;\r\n"
+ " varA = AGE_X ;\r\n"
+ " }";
detectEquals(text2);
}
public static String detectEquals(String text) {
String a = null;
// text = text.trim();
// text = TestSplitting.addDelimiters(text);
String[] newString = text.split(" ");
List<String> test = Arrays.asList(newString);
StringBuilder strBuilder = new StringBuilder();
HashMap<String, List<Integer>> signs = new HashMap<String, List<Integer>>();
HashMap<String, List<Integer>> references = new HashMap<String, List<Integer>>();
HashMap<Integer, Integer> indexesOfStringAndList = new HashMap<Integer, Integer>();
List<String> testList = new ArrayList<String>();
List<Integer> lastList = new ArrayList<Integer>();
List<Integer> indexList = new ArrayList<Integer>();
List<Integer> refList = new ArrayList<Integer>();
List<String> keysList = new ArrayList<String>();
List<List> minList = new ArrayList<List>();
String previous = null;
int index = 0;
Object obj = new Object();
List<Integer> referenceValueList = new ArrayList<Integer>();
List<Integer> indexPosition = new ArrayList<Integer>();
String b = null;
int indexOfa = 0;
// System.out.println("a----> " + test);
List<String> anotherList = new ArrayList(test);
for (int i = 0; i < anotherList.size(); i++) {
a = anotherList.get(i).trim();
index = strBuilder.length();// - a.length();
// index = i;
strBuilder.append(a); // "=", 3 - if, 14 - while, 36 , "=", 15
testList.add(a);
if (a.equals("if") || a.equals("=")) {
lastList.add(i);
indexOfa = i;
indexesOfStringAndList.put(index, indexOfa);
refList.add(index);
indexPosition.add(index);
if (signs.containsKey(a)) {
signs.get(a).add(index);
} else {
signs.put(a, refList);
}
refList = new ArrayList<Integer>();
}
if (referenceList.contains(a)) {
indexList.add(index);
if (references.containsKey(a)) {
references.get(a).add(index);
} else {
references.put(a, indexList);
}
indexList = new ArrayList<Integer>();
}
}
for (String k : references.keySet()) {
keysList.add(k);
referenceValueList = references.get(k);
obj = Collections.min(referenceValueList);
int is = (Integer) obj;
ArrayList xx = new ArrayList();
xx.add(new Integer(is));
xx.add(k);
minList.add(xx);
}
for (List q : minList) {
Integer v = (Integer) q.get(0);
String ref = (String) q.get(1);
int x = closest(v, indexPosition);
int lSize = anotherList.size();
int sizeVar = lSize - test.size();
int indexOfPx = 0;
int px = 0;
if (x != 0) {
px = indexesOfStringAndList.get(x) - 1;
} else {
px = indexesOfStringAndList.get(x);
}
if (px == 0) {
System.out.println("previous when x=0 " +anotherList.get(px+sizeVar));
anotherList.add(px, "tempVar1=\r\n");
} else {
previous = anotherList.get(px + sizeVar);
System.out.println("previous is---> " + previous + " at position " + anotherList.indexOf(previous));
anotherList.add(anotherList.indexOf(previous) - 1, "\r\ntempVAR=");
}
}
strBuilder.setLength(0);
for (int j = 0; j < anotherList.size(); j++) {
b = anotherList.get(j);
strBuilder.append(b);
}
String stream = strBuilder.toString();
// stream = stream.replaceAll(CR_STRING, CARRIAGE_RETURN + EMPTY + NEW_LINE);
System.out.println("after ----> " + stream);
return stream;
}
public static int closest(int of, List<Integer> in) {
int min = Integer.MAX_VALUE;
int closest = of;
for (int v : in) {
final int diff = Math.abs(v - of);
if (diff < min) {
min = diff;
closest = v;
}
}
return closest;
}
}
I've mapped the positions of the "=" and "if" to their positions in the StringBuilder, but these are remnants from when i was trying to use a stringBuilder to do what i said above.
I have been struggling with this for a few days now and still haven't managed to do what i need, i am not sure where i am going wrong. At the moment i am hellbent on making this work as it is (with either lists or string builder) after which , if there is a better way i will look into that and adapt this accordingly.
The addDelimiters() method is a method i created to avoid writing the string as you see it in "String text2" but i took that out for this because it would only clutter my already chaotic code even more :), i don't think it has any relevance to why what i am trying to do is not working.
TLDR: at the line above front of every varX or varY or other "var" i would like to be able to add a string to the list but i think my logic in getting the variable names or in adding to the list is wrong.
I think we both know that your code is messed up and that you need many more abstractions to make it better. But you could make it work by maintaining an offset variable, lets say "int offset". Each time you insert a string after the initial pass you increment it, and when you access the list you use it, "list.get(index+offset);". Read up on Abstract syntax trees. , which are a great way to parse and manipulate languages.