I have a task and I have some problems with it - hard to change a mindset i guess.
I need to create a collection, which keep integers and must perform such functions as:
Add and remove elements by its index and value (okay, i think it can be ArrayList or LinkedList, am I right?)
In case if element will be added other elements must be increased by a value of added element.
In case if element will be removed other elements must be decreased by a value of added element.
Last two functions..I have no clues how to make it. Probably some of you can show me a direction, where I need to move and what I need to do?
In my mind I need to create LinkedList (it allows me to remove elements by its index and value) and use some wrapped types for list. But how?
UPDATE
To clarify (from comments), this is the desired result of calling add() and remove():
add(1): [1]
add(2): [3, 2] // Existing values are incremented
add(3): [6, 5, 3]
add(4): [10, 9, 7, 4]
add(0): [10, 9, 7, 4, 0]
add(5): [15, 14, 12, 9, 5, 5]
remove(3): [15, 14, 12, 9, 5, 5] // Value not found, so no change
remove(9): [6, 5, 3, -4, -4] // All values are decremented
remove(5): [1, -2, -9, -9]
I would use an ArrayList. You can add elements in a specific index with
add(index, value)
You can remove elements by index with
remove(index)
For the second function, you can iterate the full ArrayList and add the value of the new element. After that, you add it to the ArrayList. For the third function you do it the opposite way: fist remove it and then you decrease its value to the remainig elements.
Last thing, remember you shouldn't (in fact I think you can't) remove an element of the ArrayList while you iterate it. So if you want to remove an element by its value, you can iterate the ArrayList keeping the indexes of the elements you want to remove, and then remove them. Hope it helps.
I think you need to get familiar with Java API Collection first, when you do that I'm pretty sure you will be able to resolve what you want.
I recommend this site: http://www.java2novice.com/java-collections-and-util
If I understood your question correctly, you don't need to change the elements in your collection to implement addition and subtraction (from all elements):
You could store in a variable (lets call it diff) the difference between the elements in the collection and the required result and update diff each time you add or remove an element.
Note that when you add an element, you probably have to alter the added element according to diff.
Example:
adding 1 to the array: [0], diff=1, array + diff: [1]
adding 2 to the array: [0, -1], diff=3 , array + diff: [3, 2]
adding 3 to the array: [0, -1, -3], diff=6, array + diff: [6, 5, 3]
removing 5 from array (actually removing 5-diff): [0, -3], diff=1, array + diff: [1,-2]
you can use ArrayList no need to use linkedlist in your use case
you need to iterate over the list and sum the integer with the existing values and add it to the list
you need to check if the list contains the Integer before removing it
you can try this code
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
addAndSum(list, 1);
System.out.println(list);
addAndSum(list, 2);
System.out.println(list);
addAndSum(list, 3);
System.out.println(list);
addAndSum(list, 4);
System.out.println(list);
addAndSum(list, 0);
System.out.println(list);
addAndSum(list, 5);
System.out.println(list);
removeAndSustract(list, 3);
System.out.println(list);
removeAndSustract(list, 9);
System.out.println(list);
removeAndSustract(list, 5);
System.out.println(list);
}
private static void addAndSum(List<Integer> list, Integer i) {
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) + i);
list.add(i);
}
private static void removeAndSustract(List<Integer> list, int i) {
if (list.contains(i)) {
list.remove((Integer) i);
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) - i);
}
}
the output
[1]
[3, 2]
[6, 5, 3]
[10, 9, 7, 4]
[10, 9, 7, 4, 0]
[15, 14, 12, 9, 5, 5]
[15, 14, 12, 9, 5, 5]
[6, 5, 3, -4, -4]
[1, -2, -9, -9]
Related
Why do the second and third sets preserve order:
Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i);
HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi);
LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o);
Here's the output I get:
3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9
The second one (just using HashSet) is only a coincidence. From the JavaDocs:
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.
The third one (LinkedHashSet) is designed to be like that:
Hash table and linked list implementation of the Set interface, with predictable iteration order. 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. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)
#Behrang's answer is good but to be more specific, the only reason why the HashSet seems to be in the same order as the LinkedHashSet is that integer.hashCode() happens to be the integer value itself so the numbers happen to be in order in the HashSet internal storage. This is highly implementation specific and as #Behrang says, really a coincidence.
For example, if you use new HashSet<>(4) which sets the initial number of buckets to be 4 (instead of 16) then you might have gotten the following output:
HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]
If you had stuck in values >= 16, you might get something like this:
Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]
I came across the following problem. I have an ArrayList(1) of ArrayLists(2). What I need to do is, to sort the structure so that the first elements of ArrayLists(2) to be in ascending order going down ArrayList(1). To clarify:
Input:
3, 8, 6
2, 14, 205, 44, 1
1, 3
Output:
1, 3
2, 14, 205, 44, 1
3, 8, 6
Look how it sorts the rows only based on the first value.
For now the way the arraylist of arraylists is defined for me is:
List<List<Integer>> graph = new ArrayList<List<Integer>>();
// and I add elements to it likewise
graph.get(currentIndex).add(new ArrayList<Integer>());
The reason I am using ArrayList is because I read that it is more memory efficient than LinkedList and because I am building a list of adjacency lists of a graph. In it both either the number of nodes can vary or the length of the adjacency list per node. The first element of a row is the start_node, the following - its adjacent. Could you please tell me how can I implement this sorting?
So as I understand it, you want to sort the top-level list by the first element of each nested list. Is this correct? Here is how I would go about it:
List<List<Integer>> graph = new ArrayList<List<Integer>>();
// add a bunch of things ...
// ...
// Now, to sort:
graph.sort((x,y) -> Integer.compare(x.get(0), y.get(0)));
This is using Integer to get a Comparator, which is what the sort() method requires to sort by some custom criteria. In this case, we are telling it to sort the List of Lists graph by comparing two arbitrary items in graph by getting their first items and comparing them as you normally compare Integers.
Note that this assumes all items in graph have a first item.
To compare 2 sublist you need to find the first non-equal pair, and compare their value (if both starts with like 32, you need to look next value to see)
List<List<Integer>> graph = new ArrayList<>();
graph.add(Arrays.asList(3, 8, 6));
graph.add(Arrays.asList(2, 14, 205, 44, 1));
graph.add(Arrays.asList(2, 14, 205, 44, 2));
graph.add(Arrays.asList(1, 3));
graph.add(Arrays.asList(1, 4));
graph.add(Arrays.asList(1, 4));
graph.add(Arrays.asList(1, 4, 5));
graph.sort((o1, o2) -> {
int indice, cmp, min;
for (indice = 0, min = Math.min(o1.size(), o2.size());
indice < min; indice++) {
if ((cmp = Integer.compare(o1.get(indice), o2.get(indice))) != 0) {
return cmp;
}
}
if (indice == o1.size()) return -1;
if (indice == o2.size()) return 1;
return 0;
});
System.out.println(graph);
[[1, 3],
[1, 4],
[1, 4],
[1, 4, 5],
[2, 14, 205, 44, 1],
[2, 14, 205, 44, 2],
[3, 8, 6]]
As side, another way using Comparator interface (I agree this is not very nice), it compares the value until one of the list if empty, then it will compare the size if it reaches one fully
graph.sort((o1, o2) -> {
Comparator<List<Integer>> cc = Comparator.comparingInt(l -> l.get(0));
int indice, min;
for (indice = 0, min = Math.min(o1.size(), o2.size()); indice < min; indice++) {
final int i = indice;
cc = cc.thenComparingInt(l -> l.get(i));
}
return cc.thenComparingInt(List::size).compare(o1, o2);
});
So, here is another solution I came up with.
The idea is: use the Collections' static method sort() and feed it in with the reference to the list and a new Comparator object with defined by us compare().
Collections.sort(graph, new Comparator<List<Integer>>(){
#Override
public int compare(List<Integer> aList1, List<Integer> aList2) {
return aList1.get(0).compareTo(aList2.get(0));
}
}));
In a java course homework I was asked to describe what the following code does:
while (!list1.isEmpty()) {
list2.add(list2.size(), list1.remove(0));
}
At first I thought this is actually removing the first element of list1, then add the remaining right behind list2.
But after I run a simulation program as following:
import java.util.*;
public class testQ1
{
public static void main(String[] args)
{
List<Integer> list1 = new ArrayList<>(Arrays.asList(1,2,3,4));
System.out.println(list1);
List<Integer> list2 = new ArrayList<>(Arrays.asList(5,6,7,8));
System.out.println(list2);
while (!list1.isEmpty())
{
list2.add(list2.size(), list1.remove(0));
}
System.out.println(list2);
}
}
It gives me the result:
[1, 2, 3, 4]
[5, 6, 7, 8]
[5, 6, 7, 8, 1, 2, 3, 4]
So I try to print "list1.remove(0)" before the while loop to see what it is. Then the result becomes:
[1, 2, 3, 4]
[5, 6, 7, 8]
1
[5, 6, 7, 8, 2, 3, 4]
Now it prints "1" as what "list1.remove(0)" is. And merge the remaining list1 into list2 just as I thought before.
From What I know, remove(int index) method is used to removes the element at the specified position in this list.
My question then is: What exactly does list.remove(int index) give as a result?
Thanks!
List::remove returns the element that was removed. You removed a 1, so that's what was returned.
Always check the docs first for questions like this. The documentation of the method explains what the return value represents. With a library as mature as Java's, the docs will explain 99% of your questions.
Just remove the element, then return the list.
Here is my code
import java.util.*;
public class ArrayExample {
public static void main(String[] args) {
Integer arr[] = {5,4,3,2,15,8,9};
List<Integer> list = Arrays.asList(arr);
Collections.sort(list);
System.out.println(list);
list.add(6);// here I am adding 6 to my array.
System.out.println(list);
// Here I should get output as [2,3,4,5,6,8,9,15]
}
}
You can't because this declaration :
List<Integer> list = Arrays.asList(arr);
From documentation :
Arrays.asList Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
This method acts as bridge between array-based and collection-based
APIs, in combination with Collection.toArray(). The returned list is
serializable and implements RandomAccess.
for that you can't add to this list, even if you try to remove list.remove(index); this not work.
so to solve your problem you can use :
List<Integer> list = new ArrayList<>();//declare the list
for(Integer i : arr){
list.add(i);//add element by element to the list
}
Or simply you can use :
List<Integer> list = new ArrayList<>(Arrays.asList(arr));
//----------------------------------^------------------^
If you want the array to stay sorted, you will have to sort it after each insert.
However, using a binary search, you could also find the index i where the item should be inserted and insert it there using list.add(i,6). Which would be more efficient.
No you cannot add, as you are using Arrays.asList(arr);
List<Integer> list = Arrays.asList(arr);
asList returning a fixed-size list, you cannot add any element in that, once the list is formed.
You may get java.lang.UnsupportedOperationException
[2, 3, 4, 5, 8, 9, 15]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at Test.main(Test.java:14)
You can add an element without using a list by using 2 arrays: a source array src and a destination array dest. The destination array will have one more element than the source one. You simply need to copy all the elements of the source array to the destination, and add your new element. Depends on different requirement of your post title & your post body, I added 2 solutions:
Solution 1
This solution add an element to your array AFTER sorting the array, as mentioned in the post title. But please notice that the element added is located at the tail of the new array.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
Arrays.sort(src);
System.out.println(Arrays.toString(src));
// [2, 3, 4, 5, 8, 9, 15]
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 8, 9, 15, 6]
// ^
Solution 2
This solution add an element to your array BEFORE sorting the array. It contains the expected array as mentioned in your code comment in the post body.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
Arrays.sort(dest);
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 6, 8, 9, 15]
// ^
See also:
Sorting methods in Arrays (Java Platform SE 8) - Oracle Help Center
System#arraycopy(Object, int, Object, int, int)
Let's assume we have an array of 10 elements a[] = {2, 3, 4, 5, 3, 2, 3, 3, 3, 2}; and if have to check the number of occurrences of an specific element say 3 . Then how I will able to count it without loop? Because the number of elements may be so many. My question is: is there any Java method to find it?
Without writing a traditional for loop:
List<Integer> list = Arrays.asList(2, 3, 4, 5, 3, 2, 3, 3, 3, 2);
long occurences = list.stream().filter(n -> n == 3).count();
System.out.print(occurences);
With an array which is an object where you you have to iterate over elements to know each one, a loop is unavoidable.
My question is: is there any Java method to find it?
Yes but you should use a structure more suitable to your need such as a Map for example.
The idea is to use a Map to initialize values and the associated frequency. In this way, you didn't need any longer to perform loop when you want to know the frequency of a integer value.
public Map<Integer,Integer> createWithElements(int... values) {
Map<Integer,Integer> nbOccurencesByValue = new HashMap<>();
for (int value : values){
Integer actualNbOccurence = nbOccurencesByValue.get(value);
if (actualNbOccurence==null){
actualNbOccurence=0;
}
nbOccurencesByValue.put(value, ++actualNbOccurence);
}
return nbOccurencesByValue;
}
How to use it :
Map<Integer,Integer> nbOccurencesByValue = createWithElements(2, 3, 4, 5, 3, 2, 3, 3, 3, 2);
Integer nbOccurenceFor3Number = nbOccurencesByValue.get(3);