How to access array of linked list? - java

I've created an array of LinkedList of Connection objects using the second answer from here. That is, I've done:
LinkedList<Connection>[] map = (LinkedList<Connection>[]) new LinkedList[count];
However, I am confused as to how to access each element of the array (ie each LinkedList) and create a new node. Right now, I have:
for (int j = 0; j < numOfConnections; j++) {
map[j].add(new Connection(s.next(), s.nextDouble(), s.next()));
}
But I think this would only add a single new node to each LinkedList element of the Array. I want to loop through and add numOfConnections amount of nodes to each LinkedList element. For example, 3 nodes in map[0], 5 nodes in map[1], 2 nodes in map[2], etc.

On your example "3 nodes in map[0], 5 nodes in map[1], 2 nodes in map[2]" if numOfConnections is the amount of values you want to add to your LinkedList[k] shoudnt you map which list to add ? eg.: numOfConnections[] = {3, 5, 2};
for ( int k = 0; k < numOfConnections.length; k++ )
{
if (map[k] == null) map[k] = new LinkedList<Connection>();
for (int j = 0; j < numOfConnections[k]; j++)
{
map[k].add(new Connection(s.next(), s.nextDouble(), s.next()));
}
}

Since you have an array of LinkedList instances:
For every bucket in the array, you need to put a new LinkedList instance
You need to add Connection instances to each LinkedList, which is contained in a bucket in the array.
You are treating your array like a List, by trying to invoke add on it.
in your loop, do something like
LinkedList<Connection> list = map[j]; // get the list for this bucket in the array
if (list == null) // if there is no LinkedList in this bucket, create one
list = map[j] = new LinkedList<Connection>();
list.add(new Connection(...));
I would change your variable name map to something like lists because Java has a Map object, and it's confusing.

Related

Iterating over List of Lists

I'm trying to iterate over a list os lists but I'm getting CME all the time even using Iterator to remove and add elements while iterating over the lists.
I searched here in the community for similar questions but those I found didn't help me. Really hope you guys help me to figure out how to do what I need to do.
I have I ListIterator<List<Event<T>>> itrListsEvent = partitionSubLists.listIterator();
partitionSubLists is A list of lists. So I have one bigger List and inside it I have four sublists.
I need to iterate over the sublists, and while iterating I remove and add elements. After finishing to iterate over the first sublist, I need to go forward to iterate over the second sublist and so on and so forth.
This is what I've done so far:
public List<List<Event<T>>> partitionedLists (List<Event<T>> list)
{
int listSize = list.size();
int partitionSize = listSize / 4;
List<List<Event<T>>> partitions = new ArrayList<>();
for (int i = 0; i < listSize; i += partitionSize)
{
partitions.add(list.subList(i, Math.min(i + partitionSize, list.size())));
}
return partitions;
}
List<List<Event<T>>> partitionSubLists = partitionedLists(List<Event<T>>);
ListIterator<List<Event<T>>> itrListsEvent = partitionSubLists.listIterator();
while(itrListsEvent.hasNext())
{
List<PrefixEvent<T>> listPE = new ArrayList<Event<T>>();
listPE = itrListsPrefixEvent.next();
ListIterator<Event<T>> itrEvent = listPE.listIterator();
while(itrEvent.hasNext())
{
//here I remove and add elements inside the sublist.
//when finished, I need to go back to first while and go forward to the next sublists
//and in this moment, i got ConcurrentModificationException
itrEvent.remove()
.
.
.
// some code here
itrEvent.add(new Event<T>);
}
}
It's rather unclear exactly what you're trying to achieve. As far as I understand, you could achieve it like this:
List<PrefixEvent<T>> listPE = itrListsPrefixEvent.next();
// No iterator.
for (int i = 0; i < listPE.size(); ++i) {
listPE.remove(i);
// some code here
listPE.add(i, new Event<>());
}
This avoids a ConcurrentModificationException because you don't structurally modify the list after creating an Iterator.
If you don't actually require the "one element removed" list in between the itrEvent.remove() and itrEvent.add(new Event<T>()), you can continue to use the ListIterator, and then set the value to a new value:
itrEvent.set(new Event<>());

compare two arraylist object not working

I have two array list with name list and sum from this kind of class :
public class Factor {
private String cat;
private String kind;
private String name;
private int number;
private String id;
}
my purpose is compare this two arraylist and if they have same object , list number = sum number else sum object add to list .
this is my try so far :
int size=list.size();
for (int j=0; j<size ;j++){
for (int i = 0; i < sum.size(); i++) {
if (list.get(j).getId().equals(sum.get(i).getId())){
list.get(i).setNumber(sum.get(i).getNumber());
} else {
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(),sum.get(i).getKind(), sum.get(i).getName(), sum.get(i).getNumber()));
}
}
}
but problem is always two condition run any way it mean do below in if list.get(i).setNumber(sum.get(i).getNumber());
and after that do below in else
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(), sum.get(i).getKind(),
sum.get(i).getName(), sum.get(i).getNumber()));
always add list ... so where am i wrong ?
Your logic was incorrect.
Based on the comments, you want to add to list all the elements of sum that don't have a matching ID in list. For that purpose you should iterate over the elements of sum first (i.e. in the outer loop).
int size=list.size();
for (int i = 0; i < sum.size(); i++) {
boolean found = false;
for (int j=0; j<size ;j++) {
if (list.get(j).getId().equals(sum.get(i).getId())) {
list.get(j).setNumber(sum.get(i).getNumber());
found = true;
break;
}
}
if (!found) {
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(), sum.get(i).getKind(),
sum.get(i).getName(), sum.get(i).getNumber()));
}
}
you need to make sure both list size is the same, so if they are not the same size they wont be equal
Also this is a bad practice to compare two lists, a better way would be using a Set, just convert one of the lists to a set ( time complexity O(n) ) then loop over the other list and check if all elements are in the set you created from the other list, also you need to take care of duplicate case , so if duplicate is allowed in the list you need to use a map , where the id is the key and the value is the number of occurrences , while iterating over the other list if the key is found decrement the number and check if its not getting less than zero.
From your question, it's still not clear what you are trying to achieve from this code. Do you wanna compare every element of list array with every element of sum array or u just want to compare list array with the corresponding element of sum array.
As per my understanding,
From your code, I can see that u are using nested loos.
***for (int j=0; j<size ;j++)
{
for (int i = 0; i < sum.size(); i++) {}}***
So for every list(j) array, it will compare this all the elements of sum(i) array and out which some will execute IF block and some will execute else block depending upon the condition.
If this is not what u are looking for they give some more clarity on ur question.

How can I check for duplicate values of an object in an array of objects, merge the duplicates' values, and then remove the duplicate?

Right now I have an array of "Dragon"s. Each item has two values. An ID and a Count. So my array would look something like this:
Dragon[] dragons = { new Dragon(2, 4),
new Dragon(83, 199),
new Dragon(492, 239),
new Dragon(2, 93),
new Dragon(24, 5)
};
As you can see, I have two Dragons with the ID of 2 in the array. What I would like to accomplish is, when a duplicate is found, just add the count of the duplicate to the count of the first one, and then remove the duplicate Dragon.
I've done this sort of successfully, but I would end up with a null in the middle of the array, and I don't know how to remove the null and then shuffle them.
This is what I have so far but it really doesn't work properly:
public static void dupeCheck(Dragon[] dragons) {
int end = dragons.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (dragons[i] != null && dragons[j] != null) {
if (dragons[i].getId() == dragons[j].getId()) {
dragons[i] = new Item(dragons[i].getId(), dragons[i].getCount() + dragons[j].getCount());
dragons[j] = null;
end--;
j--;
}
}
}
}
}
You should most probably not maintain the dragon count for each dragon in the dragon class itself.
That aside, even if you are forced to use an array, you should create an intermeditate map to store your dragons.
Map<Integer, Dragon> idToDragon = new HashMap<>();
for (Dragon d : yourArray) {
// fetch existing dragon with that id or create one if none present
Dragon t = idToDragon.computeIfAbsent(d.getId(), i -> new Dragon(i, 0));
// add counts
t.setCount(t.getCount() + d.getCount());
// store in map
idToDragon.put(d.getId(), t);
}
Now the map contains a mapping between the dragons' ids and the dragons, with the correct counts.
To create an array out of this map, you can just
Dragon[] newArray = idToDragon.values().toArray(new Dragon[idToDragon.size()]);
You may be force to store the result in an array but that doesn't mean that you're force to always use an array
One solution could be using the Stream API, group the items adding the count and save the result into an array again. You can get an example of how to use the Stream API to sum values here. Converting a List<T> into a T[] is quite straightforward but anyways, you have an example here
The size of an array cannot be changed after it's created.
So you need to return either a new array or list containing the merged dragons.
public static Dragon[] merge(Dragon[] dragonArr) {
return Arrays.stream(dragonArr)
// 1. obtain a map of dragon IDs and their combined counts
.collect(groupingBy(Dragon::getId, summingInt(Dragon::getCount)))
// 2. transform the map entries to dragons
.entrySet().stream().map(entry -> new Dragon(entry.getKey(), entry.getValue()))
// 3. collect the result as an array
.toArray(Dragon[]::new);
}

How to move data from multiple Arraylist to multiple Arrays (in Java)

I have 3 arraylist each have size = 3 and 3 arrays also have length = 3 of each. I want to copy data from arraylists to arrays in following way but using any loop (i.e for OR for each).
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
I have done it manually one by one without using any loop, but code appears to be massive because in future I'm sure that number of my arraylists and arrays will increase up to 15.
I want to copy the data from arraylists to arrays as shown in the image but using the loops not manually one by one?
How about this?
List<Integer> arraylist0 = Arrays.asList(2,4,3);
List<Integer> arraylist1 = Arrays.asList(2,5,7);
List<Integer> arraylist2 = Arrays.asList(6,3,7);
List<List<Integer>> arraylistList = Arrays.asList(arraylist0, arraylist1, arraylist2);
int size = 3;
int[] myArray0 = new int[size];
int[] myArray1 = new int[size];
int[] myArray2 = new int[size];
int[][] myBigArray = new int[][] {myArray0, myArray1, myArray2};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
myBigArray[i][j] = arraylistList.get(j).get(i);
}
}
To explain, since we want to be able to work with an arbitrary size (3, 15, or more), we are dealing with 2-dimensional data.
We are also dealing with array and List, which are slightly different in their use.
The input to your problem is List<Integer>, and so we make a List<List<Integer>> in order to deal with all the input data easily.
Similarly, the output will be arrays, so we make a 2-dimensional array (int[][]) in order to write the data easily.
Then it's simply a matter of iterating over the data in 2 nested for loops. Notice that this line reverses the order of i and j in order to splice the data the way you intend.
myBigArray[i][j] = arraylistList.get(j).get(i);
And then you can print your answer like this:
System.out.println(Arrays.toString(myArray0));
System.out.println(Arrays.toString(myArray1));
System.out.println(Arrays.toString(myArray2));
You need to have two additional structures:
int[][] destination = new int [][] {myArray1, myArray2,myArray3 }
List<Integer>[] source;
source = new List<Integer>[] {arraylist1,arraylist2,arraylist3}
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
for (int i=0;i<destination.length;i++) {
for (int j=0;j<source.length;j++) {
destination[i][j] = source[j].get(i);
}
}
If you cannot find a ready made API or function for this, I would suggest trivializing the conversion from List to Array using the List.toArray() method and focus on converting/transforming the given set of lists to a another bunch of lists which contain the desired output. Following is a code sample which I would think achieves this. It does assume the input lists are NOT of fixed/same sizes. Assuming this would only make the logic easier.
On return of this function, all you need to do is to iterate over the TreeMap and convert the values to arrays using List.toArray().
public static TreeMap<Integer, List<Integer>> transorm(
List<Integer>... lists) {
// Return a blank TreeMap if not input. TreeMap explanation below.
if (lists == null || lists.length == 0)
return new TreeMap<>();
// Get Iterators for the input lists
List<Iterator<Integer>> iterators = new ArrayList<>();
for (List<Integer> list : lists) {
iterators.add(list.iterator());
}
// Initialize Return. We return a TreeMap, where the key indicates which
// position's integer values are present in the list which is the value
// of this key. Converting the lists to arrays is trivial using the
// List.toArray() method.
TreeMap<Integer, List<Integer>> transformedLists = new TreeMap<>();
// Variable maintaining the position for which values are being
// collected. See below.
int currPosition = 0;
// Variable which keeps track of the index of the iterator currently
// driving the iteration and the driving iterator.
int driverItrIndex = 0;
Iterator<Integer> driverItr = lists[driverItrIndex].iterator();
// Actual code that does the transformation.
while (driverItrIndex < iterators.size()) {
// Move to next driving iterator
if (!driverItr.hasNext()) {
driverItrIndex++;
driverItr = iterators.get(driverItrIndex);
continue;
}
// Construct Transformed List
ArrayList<Integer> transformedList = new ArrayList<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
transformedList.add(iterator.next());
}
}
// Add to return
transformedLists.put(currPosition, transformedList);
}
// Return Value
return transformedLists;
}

Iterating through multiple lists

I have two seperate lists from a DTO i created, the two lists are containing different set of data i.e in first list lets say there are some 'userloginname' along with 2nd last updated 'status'.
In the 2nd List i have 'userloginname' with all the status record(not just the 2nd last updated status).
Is this possible if want to take each 'userloginname' from List1 and compare with each 'userloginname' in the list2 with some condition.?
thank you
Correct me if I'm misunderstanding, but how about something like this:
for (int i = 0 ; i < list1.size() ; i++) {
// Do something with "list1.get(i)" and "list2.get(i)"
}
With this you can compare items at a given index in list1 with items at the corresponding index in list2. If you want to compare every list1 member with every other list2 member, you could do something like:
for (int i = 0 ; i < list1.size() ; i++)
for (int j = 0 ; j < list2.size() ; j++) {
// Do something with "list1.get(i)" and "list2.get(j)"
}
Convert one of the lists to a map using 'userloginname' as a key.
List<LastStatusRecord> lastStatusRecords = dto.getLastStatusRecords();
List<StatusRecord> statusRecords = dto.getStatusRecords();
Map<String, FullRecord> statusRecordIndex = new HashMap<String, StatusRecord>();
for (StatusRecord statusRecord : statusRecords) {
statusRecordIndex.put(statusRecord.getUserLoginName(), statusRecord);
}
for (LastStatusRecord lastStatusRecord : lastStatusRecords) {
StatusRecord statusRecord = statusRecordIndex.get(lastStatusRecord.getUserLoginName());
// place the condition here
}

Categories