Can someone suggest me a datatype/structure in java that satisfies:
1) no fixed size
2) does not automatically sort data. Data should be stored in the order in which it arrives
3) it should store only unique entries
4) its elements are accessible or atleast the first element should be!
links are not able to maintain unique entries.
I tried working with Sets but it changes the order of my data automatically which i dont want to let happen.
So i am now trying to work my way with LinkedHashSet, but I am not able to find the exact way to access the first element of the same for comparision.
Any suggestions please. Thanks!
You can use LinkedHashSet if you don't wanna write your own structure. Getting elements may be kinda tricky, try this:
Integer lastInteger = set.stream().skip(set.size()-1).findFirst().get();
This is gonna get the last element, if you want different elements you need to skip a different count. This is only one of the ways, you can get an iterator and iterate yourself etc. Remember to override hashCode and equals when working with sets.
LinkedHashSet is the right data structure for your requirements.
You can access the first element like so:
Set<String> set = new LinkedHashSet<>();
set.add("a");
set.add("b"); // And so on
// Retrieve first element
// Will throw NoSuchElementException if set is empty
String firstElement = set.iterator().next();
// Retrieve and remove first element
Iterator<String> i = set.iterator();
String otherFirstElement = i.next();
i.remove();
For accessing other elements, see answer from #Whatzs.
If I properly understand your question, you are looking for a data structure that would combine the properties of a Set and an ArrayList, a kind of "ArraySet".
I haven't found anything in the core java for that but it looks like the Android JDK has such a data structure.
https://developer.android.com/reference/android/util/ArraySet.html
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/ArraySet.java
One solution might be to build your own based on the android implementation.
Related
I have an Iterable<MyRecord> records . I iterate over the records like below and add it to a LinkedList as shown below.
for (MyRecord record: records){
sortedList.addLast(record);
}
My iterable has 3 records, all with different values. But in the end although sortedList contains 3 records, ALL THREE ARE THE SAME!!!. How come?
When I printed out the memory location, it's the same for all 3. What am I doing wrong?
Actually your comment reveals the missing link to why this is going wrong. You're using this in a Hadoop mapper or reducer. The trick with Hadoop is that it reuses the objects you're getting in, so that it goes easy on the garbage collector. What you thus have to do is make a copy of each of the objects in your source iterable (the MyRecords), and add those to your LinkedList.
If the sortedList contains the same records, which is the last elements in original records, it's possible that the iterator re-use the tmp reference. You need to check the implementation of the 'records'.
Your question is clear and so is the code (also after reading the comments); this may not help, but maybe you can just do, before your add, a contains check like: if (sortedList.contains(record)) sortedList.add...
I admit this might not really help (also i don't know if contains checks for element memory location under the hood, as i guess it might only check for element presence in the list using equals).
When you are adding items into the list put check :
if(sortedList.contains(record))
{
System.out.println("Record is already available "+record);
}
else
{
sortedList.addLast(record);
}
You will get to know whether the problem is due to same records or because of something else.
Is there any way to know what was the last new entries that were added to a hashset ? In my program the first cycle adds [Emmy, Carl] and than on my second cycle it adds [Emmy, Dan, Carl] is there anyway I can just use dan and not the rest of them for cycle three ?
java.util.HashSet does not preserve order, but java.util.LinkedHashSet does. Can you use that instead? From the Javadoc:
This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set.
HashSets do not carry information about the order in which you add elements. You need to replace it with a Collection that does (e.g. ArrayList).
Hashset are backed by hash tables and there is no guarantee on the order of retrieval. The order of retrieval will not be the same as the order of insertion. So, no it's not possible to know which item was added last.
Workarounds - may be use two hashsets, compare old with new and get the new entries or have some sort of indicators to distinguish the perticular iteration it was added or use ArrayList or anything that fits in your design.
HashSet<String> oldpeople = new HashSet<String>();P
HashSet<String> newPeople;
for (Set<String> cycle : input)
{
newPeople = new HashSet<String>();
newPeople.addAll(cycle);
newPeople.removeAll(oldPeople);
oldPeople.addAll(cycle);
}
now you have the last new one always contained in newPeople.
Well if I understand your post and the comments correctly (well that's quite hard, try to be bit more precise :) ) what you actually want is: a) not add any items several times to the HashSet and b) see if the set already contains the given item when trying to add it.
a) is trivially true for every set and for b) you can just use the return value of add: If it returns false is already contained in the set.
So far I have what's written below but how would I make sure the item to add returns to it's alphabetized spot?
I'm in a beginner class so I cannot use ArrayLists or the methods assoicated with them.
Any sort of help or push in the right direction would be appreciated. Thanks!
The method should follow these instructions:
- Adds an item to the list. This method assumes that the list is already
sorted in alphabetical order based on the names of the items in the list.
- The new item will be inserted into the list in the appropriate place so
that the list will remain alphabetized by names.
In order to accommodate the new item, the internal array must be re-sized
so that it is one unit larger than it was before the call to this method.
public void add(Listable itemToAdd) {
Listable[] items1;
int newlength = items.length+1;
items1 = new Listable [newlength];
for(int i = 0;i<items.length;i++){
items1[i] = items[i];
items1[newlength-1] = itemToAdd;
}
}
That's not bad for a start! There are a number of things we need to do. This line
items1[newlength-1] = itemToAdd;
needs to come out of the loop, and be placed afterwards -- you'll set some array element to this value just once, yes, and not many times?
The copying part is a good start. What you need to do is
Find the location where the new element should go (search through the array, and find the element that the new one should go after)
Copy the elements that go before the new element
Copy the new element
Copy the elements that go after the new element (adjusting their indexes, since they're all one later than they used to be!)
Make sense?
If you're in a beginner class, you may have learned about insertion sort. One of the interesting properties of insertion sort is that despite its poor runtime in the average case (O(n2)), its performance in the best case (a sorted list) is quite good - O(n), in fact. An almost-sorted list would run in the same efficiency class. That might be a way to accomplish what you're trying to do. (It also might be one of the few places you'll ever use insertion sort, so make the most of it.)
I'm using Groovy and Grails and am trying to take a parameter passed to a controller, parse it, and add each individual element into a list. I thought this would work, but it is adding the whole string into the list, leaving me with only one element.
list = []
list.add(params["firstNames"].split())
is returning a list with size 1, with the list element being a string containing all the names.
also, if I do list = params["firstNames"].split()) , it is showing a size of 2 (i have two elements) but it is still treating it as a String and I cannot perform any other list operations on it.
what is it that I'm doing wrong?
thanks for the help.
Try a variation of this:
String foo = 'foo,bar,baz'
def list = foo.split(',') as List
assert list instanceof java.util.List
assert list.size() == 3
The key part is the as List. If this doesn't work for you, make sure you're using the correct delimiter argument to split(). If you can provide us with an example of what the parameter value might be, we can probably provide a better answer.
First of all, this is my code (just started learning java):
Queue<String> qe = new LinkedList<String>();
qe.add("b");
qe.add("a");
qe.add("c");
qe.add("d");
qe.add("e");
My question:
Is it possible to add element to the queue with two values, like:
qe.add("a","1"); // where 1 is integer
So, that I know element "a" have value 1. If I want to add a number let say "2" to element a, I will have like a => 3.
If this cant be done, what else in java classes that can handle this? I tried to use multi-dimention array, but its kinda hard to do the queue, like pop, push etc. (Maybe I am wrong)
How to call specific element in the queue? Like, call element a, to check its value.
[Note]
Please don't give me links that ask me to read java docs. I was reading, and I still dont get it. The reason why I ask here is because, I know I can find the answer faster and easier.
You'd want to combine a Queue<K> with a Map<K,V>:
Put the keys (e.g. "a", "b") into the Queue<K>
Assign the mapping of the keys to values (e.g. "a"=>3) in the Map<K,V>
I think you're asking for a dictionary type in Java.
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
You can then access them by key - in this case the String you choose as the key.
int value = map.get("a");
Value in this case will return 1.
Is that what you want?
You want to use a HashMap instead of LinkedList. HashMap is a dictionary-like structure that allows you to create associations, for instance a=>1.
Check out JavaDocs for HashMap to get a grasp how to use it:-).
I think what you are asking for is LinkedHashMap which is a combination of a Queue and a HashMap. While you are able to store the key and value pairs, it would also remember the order like Queue does. The only thing is you'd have to use an iterator since there is no poll() method, however you can visit each element in the order that they were added.