So I am implementing a mapreduce job which means I am dealing with key value pairs.
I have the variable
Iterable<FreqDataWritable> values
FreqDataWritable is an object that contains pieces of information, but for now I am only concerned with one piece of information it holds which is a String which is accessed by getFilename().
I have the following loop:
ArrayList<String> filenames = new ArrayList<String>();
for(FreqDataWritable i : values) {
filenames.add(i.getFilename());
}
Now all I want to do is print the values in the array list filenames.
for(int i = 0; i < filenames.size(); i++) {
System.out.println(filenames.get(i));
}
However when I do this everything in filenames is the same. The only thing printed out is a single filename printed multiple times.
My original code is more complex than this, but I simplified it for help. Anyone know how to fix this?
Thanks
I figured it out. Hadoop has an odd memory usage so when I iterated over the values the first time it was just adding the same object over and over again to the arraylist.
Instead I need to do this:
for(FreqDataWritable i : values) {
filenames.add(new String(i.getFilename()));
}
for(String filename : filenames) {
System.out.println(fn);
}
Let me know if this will help?
Have you tried an iterator-based method?
Iterator i = values.iterator();
fileNames.add(i.next().getFileName());
for(i; i.hasNext();) {
String stringI = i.next().getLast().getFileName();
if(!stringI.equals(fileNames.get(fileNames.size() - 1)))
fileNames.add(i.next().getLast().getFileName());
}
Related
I have a JTable with three columns, each of which is filled with an array made from an ArrayList. I am trying to make a search system, where the user will search for a value in the first column, and the rows of the JTable will filter out, so that only the rows that contain the specified String from the search box show up on the table after a button is pressed. On another table, this worked by filtering the ArrayList used using this loop:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
for(Iterator<String> it = fn.iterator(); it.hasNext(); ) {
if (!it.next().contains(s)) {
it.remove();
}
This code works to filter out the array, but what I am trying to do is filter 3 ArrayLists based on only if one of the ArrayLists does not contain the s String.
I tried doing this:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
ArrayList<String> fp = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
fp.addAll(numbers)//one of the other arraylists that I want to filter
for(Iterator<String> it = fn.iterator(), itp = fp.iterator(); it.hasNext() && itp.hasNext(); ) {
if (!it.next().contains(s)) {
itp.remove();
it.remove();
}
When I run this code I get a Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException on the line where I write "itp.remove();".
Is there a way I can remove from both the arrays based on only one of them?
I'm happy that you fix your exception. Anyway, when I said about back iteration I meant something like that
Firstly, Some of check like
if(fn.size()==fp.size()){
// and after that go to delete.
for (int i=fn.size(); i>0;i--) {
if (fn.contains(s)) {
fn.remove(i);
fp.remove(i);
} }}
Anyway, your and my method isn't good for multithreading, because ArrayList doesnt't concurrent object also it's remove method
So I managed to fix it by using the remove method from the ArrayList instead of the remove method from the Iterator. I know this isn't the recommended way of doing it, but it seems to not have brought any negatives with it, so I will keep it for now.
The code I used is:
int i = 0;
for (Iterator<String> it = fn.iterator(); it.hasNext(); i++) {
if (!it.next().contains(s)) {
it.remove(); //Iterator's remove
fp.remove(i);// ArrayList's remove which avoids the error
}
}
Thank you to all who helped
I have to compare two Excel files (with different data) and create two new Excel tables:
Table 1 contains all matching entries
Table 2 contains all entries that not match
Therefore I iterate over both Excel files and store the matching entries in a LinkedHashMap. In a second LinkedHashMap I store all entries from the Excel file. With this two Maps I want to identify the delta.
To identify the delta I compare both lists and now want to remove all entries from the complete list, if the entry is already in the list with the matching ones.
I tried different solutions - all with the result that the code is running but never an entry is really removed. Can anyone help please?
Heres my code:
// This code fills both Maps
LinkedHashMap<String, String> liste_matches = new LinkedHashMap<String, String> ();
LinkedHashMap<String, String> liste_complete = new LinkedHashMap<String, String> ();
while(worksheet1.getLastRowNum() >= j){
liste_complete.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
// Counter for loop, loops trough Telekom datasets
int i = 1;
while(worksheet2.getLastRowNum() >= i)
{
if(String.valueOf(worksheet1.getRow(j).getCell(18)).equals(String.valueOf(worksheet2.getRow(i).getCell(9))))
{
if(!liste_matches.containsKey(String.valueOf(worksheet1.getRow(j).getCell(18)))){
liste_matches.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
}
}
}
// build Excel table
}
This is my code I used to compare both lists and remove all entries from liste_complete that are already in liste_matches.
I first tried this (I inserted the ArrayList for my second try...). It's running but without any effect to the list.
ArrayList list = new ArrayList();
for(Map.Entry<String,String> keyDelta : liste_complete.entrySet())
{
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(keyDelta.equals(key)){
liste_complete.remove(keyDelta);
list.add(entry.getValue());
}
}
}
Afterwards I tried this but also without any effect to the List:
for(int c = 0; c < list.size(); c++)
{
String str = list.get(c);
liste_complete.remove(str);
}
I found this solution in StackOverflow, but that returns java.lang.IllegalStateException
Iterator<Map.Entry<String,String>> iter = liste_complete.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> entry = iter.next();
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(key.getValue().equalsIgnoreCase(entry.getValue())){
iter.remove();
}
}
}
AFAIK you can't remove element from a list you're iterating on.
I suggest you 2 solutions:
iterate on your lists to check for matching keys and store the match in the third list; then iterate on the third list and remove from liste_complete
refactor the first piece of code of your question so that you store in one list the matching values and in the other the non-matching. Pseudo code could be:
for worksheet1 row
for worksheet2 row
if(match)
liste_matches.add(...)
else
liste_non_matches.add(...)
In this way you do not have to remove elements afterwards.
Thanks a lot for your hints.
I already debugged the code but didn't understand the problem - I think it really was a problem of the complex input data.
I did not compare the keys via key.getKey() but only with key and that seems to cause problems in the comparison. Anyway, my code runs with this snippet:
for(Map.Entry<String,String> keyDelta : liste_Complete.entrySet()){
if(!liste.containsKey(keyDelta.getKey())){
delta_liste.put(String.valueOf(keyDelta), "");
}
}
I am having some trouble with removing values that do not match a given value. At the moment I am copying over values to a new list and trying to clear the original list - but this is inefficient.
This is my code:
int size = list.size();
ArrayList<String> newList;
int count = 0;
newList = new ArrayList<>();
for (int i=0; i<list.size(); i++){
if(list.get(i).getForename().equals(forename)){
newList.add(i, list);
}
}
list.clear();
Is there a way where I can just remove an item in the arraylist if it does NOT match the name?
EDIT:
It works but then I might need a copy, as if I select a another name from the dropdown it will be referring to the old one
Thanks
A first thought would be to iterate on the list and as soon as you find an item not matching the value, you remove it. But it will create a Concurrent modification exception, as you iterate on list while trying to remove elements in it.
An other, still not efficient would be to iterate on the list, keep track of the indexes to remove, and after iterating on the list, remove them.
ArrayList<Integer> indexList = new ArrayList<Integer>();
for(int i = 0; i<list.size(); i++){
if(!list.get(i).getForename().equals(forename)){
indexList.add(i);
}
for(Integer index : indexList){
list.remove(index);
}
indexList.clear();
Please not that this is not really efficient too, but maybe you were looking for a way to delete from the same list.
A simple solution is
while (list.contains(value)) {
list.remove(list.indexOf(value));
}
Depending on what you want, you might want to use streams instead (seems to be what you actually want, since you don't really seem to want to delete elements in your list):
newList = list.stream()
.filter(e -> getForename().equals(forename))
.collect(Collectors.toList());
or to perform your action what you might want to do:
list.stream()
.filter(e -> getForename().equals(forename))
.forEach(person -> doStuff(person));
Another way would be using iterators to avoid conflicts with modifications during iteration:
ListIterator iterator = list.listIterator();
while(iterator.hasNext()){
if(!iterator.getNext().getForename().equals(forename))
iterator.remove();
}
EDIT: Since OP can't use lambdas and streams (because of Java-version), here is what nearly happens for the second stream (the forEach). I am not using the proper interfaces, since OP can't do so either. The difference to streams is, that they also might split this into several threads and hence would be faster (especially on multi-core processors and big lists):
interface Consumer<T>{ //this is normally given by the JAVA 8 API (which has one more default method)
void accept(T t);
}
Consumer<YourObject> doIt = new Consumer<YourObject>(){ //This is what the lambda expression actually does
#Override
public void accept(YourObject e) {
doStuff(e);
}
};
for(YourObject element : list){ //since JAVA 1.5. Alternativ your old for-loop with element=list.get(i);
if(!element.getForename().equals(forename)) //the filter written in easy
continue;
doIt.accept(element); //You could also use a method or expressions instead in this context.
//doStuff(element); //What actually the upper stream does.
}
You might want to look at the oracle tutorial (this chapter) to get a feeling, when this design is appropriate https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html (I have a strong feeling, you might want to use it).
Assuming your List contains String objects the following should be what you are looking for:
for (Iterator<String> it = list.iterator(); it.hasNext()){
String foreName = it.next();
if(forName != null && foreName.equals(forename)){
it.remove();
}
}
try
for (int i=0; i<list.size();){
if(!list.get(i).getForename().equals(forename)){
list.remove(i);
}
else {
i++;
}
}
In my class Feeds I have along with other members a member variable called "Date" which is of String type. I have an ArrayList of Feeds objects. I want to find the occurrences of objects which have the same date String. The occurrences can then be put in a HashMap that contains the String Date as key and # of occurrences as value.
Something along these lines:
List<Feeds> m_feeds = new ArrayList<Feeds>();
//add all feeds objects
m_feeds.add(...);
int occurrences = 0;
HashMap<String, Integer> repeatedDatabase = new HashMap<String, Integer>();
for (Feeds f : m_feeds){
occurrences = Collections.frequency(m_feeds, f.date);
// i know this method compares objects but i want to know how
// only a single variable can be done
repeatedDatabase.put(f.date, occurrences);
}
Other than giving you a simple solution, I took the liberty of fixing some things in your code please take a look:
List<Feeds> mFeeds = new ArrayList<>(); //If you are using Java 7+ you do not need to declare explicitly the Type in Diamonds. If you aren't, ignore this. Also fixed name to adapt to Java standards.
//add all feeds objects
m_feeds.add(...);
HashMap<String, Integer> repeatedDatabase = new HashMap<>(); //See Above.
for (Feeds f : m_feeds){
String s = f.date; //Suggestion: use a getter method, do not make public variables accessible outside class
Integer i = repeatedDatabase.get(s);
if (i == null){
repeatedDatabase.put(s, 1);
} else {
repeatedDatabase.put(s, i+1);
}
}
Your code will work if you properly overrode equals and in the Feeds class to return true for two Feeds instances having the same date (since if you try to put the same key in the Map twice, the new value will override the old value, and since in your case the values would also be the same, it would make no difference). However, each call to Collections.frequency would iterate over the entire List, which would give you an O(n^2) time complexity.
One way to make it more efficient :
for (Feeds f : m_feeds){
if (!repeatedDatabase.containsKey(f.date)) {
occurrences = Collections.frequency(m_feeds, f.date);
repeatedDatabase.put(f.date, occurrences);
}
}
This would still do more iterations than necessary. It would call Collections.frequency once for each unique date, which means you would iterate the List as many times as there are unique dates.
A more efficient implementation will not use Collection.frequency at all. Instead, you'll iterate just one time over the list and count the number of occurrences of each date yourself. This would give you an O(n) time complexity.
for (Feeds f : m_feeds){
if (!repeatedDatabase.containsKey(f.date)) {
repeatedDatabase.put(f.date, 1);
} else {
repeatedDatabase.put(f.date, repeatedDatabase.get(f.date)+1);
}
}
Why don't use directly the hashMap?
you can do something like
HashMap<String,Iteger> map = new HashMap<>();
for (Feeds f : m_feeds){
if (map.contains(f.getDate()) { // use the method to get the date
map.put(f.getDate(),map.get(f)+1);
else
map.put(f.getDate(),1);
}
I didn't test the code but it should work.
A small update to Angelo's answer..pushing it a bit further.. you can also use a map of string,int[] like this
Map<String,int[]> map = new HashMap<>();
int[] countArray = map.get(key);
if(countArray == null)
map.put(key, new int[]{0});
else
countArray[0]++;
Using the beauty of references :)
I am reading from a text file and saving the lines into an ArrayList. But I have had no success in how to go through and read all of the specific characters in the ArrayList, how many columns and rows there are.
This is the code I have written so far:
String line;
BufferedReader br = new BufferedReader(r);
ArrayList<String> myArrayList = new ArrayList<String>();
while ((line = br.readLine()) != null)
{
myArrayList.add(line);
.........
}
If I am reading your post right you are wanting to further break apart your lines (your reference to columns). Since you are storing String objects you will need to further break apart those entries into another List to truly parse through your words and characters appropriately.
Java used to have something called the StringTokenizer which could do what you want but that is now deprecated and replaced by the String.Split() method. By iterating through your ArrayList and splitting the String Object by specific delimiters (such as a space or a period), you should be able to further breakdown your existing ArrayList and create a new List with individual words, or even characters.
I do not know why you use "store.add(line)". You should use myArrayList instead of this.
After you have stored everything in the ArrayList you can use a for-each loop to traverse through the list:
for (String string : myArrayList) {
// do everything with the strings here
}
You aren't calling the List myArrayList, I think you want to change this
ArrayList<String> myArrayList = new ArrayList<String>();
to (using the diamond operator and the interface type) -
List<String> store = new ArrayList<>(); // <-- match the name.
You can count the "rows" by getting the size of the List -
int rows = store.size();
To count "columns" you would need to iterate the List and examine the lines. (or you could do that while you read the input) -
for (String line : store) {
// count columns in line
}
If you want to go through a ArrayList there are many ways that you can try
You can easily get number of elements in the ArrayList using size() method.
e.g.
//traditional way
for(int i = 0; i< arrayList.size(); i++){
System.out.println(arrayList.get(i));
}
//enhanced forloop
if your ArrayList is String type
for(String row : arrayList)
System.out.println(row);
With Java 8 you cane have more easier iterator that can use to go through the ArrayList
Edited
If you wanna read character by character
for(String row : arrayList){
char []letters = row/toCharArray();
for(char character : letters)
System.out.print(character + " ") ;
}