I am working on a program to count the positive values in an integer Collection and having an issue. I am somewhat new to Java, and wondering if someone would be able to point out where I went wrong.
public class CountPositives {
/**
* Returns the number of positive values in the given Collection.
*/
public static int countPositives(Collection<Integer> collection) {
List<Integer> copy = new ArrayList(collection);
int positive = 0;
Iterator<Integer> itr = copy.iterator();
for (int i = 0; i < copy.size(); i++) {
if (copy.get(i) > 0 ) {
positive ++;
}
}
return positive;
}
}
Your code works fine for me. (Although you have an Iterator you never use) However..
Maybe an easier way would be to do:
return (int) copy.stream().filter(e -> e > 0).count();
Which will filter out all the non positive numbers and then return the count of them. Also you can simply use the passed Collection:
public static int countPositive(Collection<Integer> collection) {
return (int)collection.stream().filter(e -> e > 0).count();
}
Which will eliminate the copy List and the extra variables.
Note that count() returns a long. If the size of collection might exceed the limit of an int, you will want to change the return type to long and not cast to an int.
You're not using the Iterator. Collections can automatically give you an iterator, so there's no need to convert it to an ArrayList to get this.
Iterator<Integer> itr = collection.iterator();
Now you actually have to use it. The for statement may look wonky to you as a beginner, but remember that a for statement starts with an optional initialization step, which can be omitted.
for(; itr.hasNext();) {
Integer value = itr.next();
// rest of your logic here
}
If you prefer, you can initialize the iterator in the for statement directly.
for(Iterator<Integer> itr = collection.iterator(); itr.hasNext();) {
Integer value = itr.next();
// rest of your logic here
}
In spite of the wasteful copying, the code appears to be fine. The critical part of the code is checking to see if there are positive values, and your code does accomplish that. This is simply making it cleaner and less ceremonious.
Related
is there a way with the index of function to return the index of a value that is part of a class like just one field of the bigger structure.. I got a simple contact class and I want to return the index when the id is a certain value .. should I be using a different structure than an arrayList it is doing most of what I want but the index of function is frustrating
I think the easiest way is to just iterate over the array, and check the condition with "if". That will be O(n).
You can use the Predicate method explained here.
Optional<Integer> indexOfMatch = IntStream.range(0, yourList.size())
.filter(i -> valueYouAreLookingFor.equals(yourList.get(i).getFieldYouAreChecking()))
.findFirst();
Or if the field holds a primitive value:
Optional<Integer> indexOfMatch = IntStream.range(0, yourList.size())
.filter(i -> valueYouAreLookingFor == yourList.get(i).getFieldYouAreChecking())
.findFirst();
If there is an element in the list that matches your predicate, indexOfMatch will have the index of that element. If not, indexOfMatch will be an empty Optional.
Regarding whether an ArrayList is the appropriate structure, generally if you are working with a list of values, an implementation of List is what you want. Whether it should be ArrayList or some other implementation depends on details of what you are doing with the list. For small list sizes, it often doesn't really matter which implementation you use.
well I switched to a vector from an array list but it did not really help but I did use a loop and the list size and just put the contact in a container each time so I could do my comparison it was kinda messy but I got the index that way.
static int SearchForContact(String ContactID) {
int temp = -1;
Contact searchCon;
for (int z = 0 ; z < contactVector.size(); z++)
{searchCon = contactVector.get(z);
if(searchCon.getId() == ContactID)
{temp = z;}
}
if (temp == -1) {
throw new IllegalArgumentException("Contact not found");
}
return temp;
}
I am iterating over the ArrayList and seeing whether the current value is the id value you want.
int yourValue = 25; //I am assuming it to be an int of value 25, you can keep it whatever you want.
for (int i = 0; i < yourArrayList.size(); i++)
{
if (yourArrayList.get(i) == yourValue)
{
return i; //returning the index value
}
}
return null; //this will run if the value doesn't exist.
Obviously, this would need to be inside a method that returns an integer that is the index. Above, yourArrayList is the ArrayList you are using, and yourValue is the value you need to find. It doesn't have to be an int.
Its a very trivial question and related to coding Style and I am just asking to make my coding style more readable
Suppose I have a Collection like linkedList and an Array and I need to iterate over both simultaneously.
currently the best way I know is to get a iterator over list and define a index variable outside the iterator loop and increment the index variable simultaneously to access both next elements {list and array}. Please refer the example below
LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
// lets suppose both have 25 elements.
// My Iteration method will be
int index =0;
for (Integer val : list) {
System.out.println(val);
System.out.println(arr[index++]);
}
so is it the only way or is there any other way I can perform this iteration in more readable and more relatable manner, where I don't have to take index variable separately.
I know it can be possible that array might have less or more elements than collection but I am only talking about the cases where they have equal and we need to iterate over Both of them.
PS : anybody can write a code that a computer can understand, actual challenge is to write code which humans can understand easily.
What you have is essentially fine: it's simple, and simple can be sufficient to make code readable.
The only thing I would caution about is the side effect of index++ inside arr[index++]: if, say, you want to use the same value multiple times in the loop body, you couldn't simply copy+paste.
Consider pulling out a variable as the first thing in the loop to store the "current" array element (which is essentially what the enhanced for loop does for the list element).
for (Integer val : list) {
Integer fromArr = arr[index++];
// ...
}
Just to point out an alternative without having a separate variable for the index, you can use ListIterator, which provides you with the index of the element.
// Assuming list and are have same number of elements.
for (ListIterator<Integer> it = list.listIterator();
it.hasNext();) {
// The ordering of these statements is important, because next() changes nextIndex().
Integer fromArr = arr[it.nextIndex()];
Integer val = it.next();
// ...
}
ListIterator is not an especially widely-used class, though; its use may in and of itself be confusing.
One of the downsides of the ListIterator approach is that you have to use the it correctly: you shouldn't touch it inside the loop (after getting the values), you have to put the statements in the right order, etc.
Another approach would be to create a library method analogous to Python's enumerate:
static <T> Iterable<Map.Entry<Integer, T>> enumerate(Iterable<? extends T> iterable) {
return () -> new Iterator<T>() {
int index = 0;
Iterator<? extends T> delegate = iterable.iterator();
#Override public boolean hasNext() { return delegate.hasNext(); }
#Override public Map.Entry<Integer, T> next() {
return new AbstractMap.SimpleEntry<>(index++, delegate.next());
}
};
}
This returns an iterable of map entries, where the key is the index and the value is the corresponding value.
You could then use this in an enhanced for loop:
for (Map.Entry<Integer, Integer> entry : enumerate(list)) {
Integer fromList = entry.getValue();
Integer fromArr = arr[entry.getKey()];
}
One option is to have 2 iterators, but I don't think it is any clearer:
for (Iterator<Integer> i1 = list.iterator(), i2 = Arrays.asList(arr).iterator();
i1.hasNext() && i2.hasNext();) {
System.out.println(i1.next());
System.out.println(i2.next());
}
But it is more robust in that it finishes at the shorter of the 2 collections.
I tried to simplify and handle size wise collections where both need not be of the same size. I believe this would work even if the sizes are not same and just one loop would suffice. Code snippet below:
LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
int maxLength= Math.max(list.size(),arr.size());
//Looping over the lengthy collection( could be Linkedlist or arraylist)
for(int i=0;i<maxLength;i++){
if(list.size()>i)
System.out.println(list[i]);
if(arr.size()>i)
System.out.println(arr[i]);
}
Hope this helps! Thanks
Say I have a list with elements (34, 11, 98, 56, 43).
Using Java 8 streams, how do I find the index of the minimum element of the list (e.g. 1 in this case)?
I know this can be done easily in Java using list.indexOf(Collections.min(list)). However, I am looking at a Scala like solution where we can simply say List(34, 11, 98, 56, 43).zipWithIndex.min._2 to get the index of minimum value.
Is there anything that can be done using streams or lambda expressions (say Java 8 specific features) to achieve the same result.
Note: This is just for learning purpose. I don't have any problem in using Collections utility methods.
import static java.util.Comparator.comparingInt;
int minIndex = IntStream.range(0,list.size()).boxed()
.min(comparingInt(list::get))
.get(); // or throw if empty list
As #TagirValeev mentions in his answer, you can avoid boxing by using IntStream#reduce instead of Stream#min, but at the cost of obscuring the intent:
int minIdx = IntStream.range(0,list.size())
.reduce((i,j) -> list.get(i) > list.get(j) ? j : i)
.getAsInt(); // or throw
You could do it like this:
int indexMin = IntStream.range(0, list.size())
.mapToObj(i -> new SimpleEntry<>(i, list.get(i)))
.min(comparingInt(SimpleEntry::getValue))
.map(SimpleEntry::getKey)
.orElse(-1);
If the list is a random access list, get is a constant time operation. The API lacks of a standard tuple class, so I used the SimpleEntry from the AbstractMap class as a substitute.
So IntStream.range generates a stream of indexes from the list from which you map each index to its corresponding value. Then you get the minimum element by providing a comparator on the values (the ones in the list). From there you map the Optional<SimpleEntry<Integer, Integer>> to an Optional<Integer> from which you get the index (or -1 if the optional is empty).
As an aside, I would probably use a simple for-loop to get the index of the minimum value, as your combination of min / indexOf does 2 passes over the list.
You might also be interested to check Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)
Here's two possible solutions using my StreamEx library:
int idx = IntStreamEx.ofIndices(list).minBy(list::get).getAsInt();
Or:
int idx = EntryStream.of(list).minBy(Entry::getValue).get().getKey();
The second solution internally is very close to one proposed by #AlexisC. The first one is probably the fastest as it does not use boxing (internally it's a reduce operation).
Without using third-party code #Misha's answer looks the best for me.
Since this is for learning purposes, let's try to find a solution that doesn't just somehow use a stream, but actually works on the stream of our list. We also don't want to assume random access.
So, there are two ways to get a non-trivial result out of a stream: collect and reduce. Here is a solution that uses a collector:
class Minimum {
int index = -1;
int range = 0;
int value;
public void accept(int value) {
if (range == 0 || value < this.value) {
index = range;
this.value = value;
}
range++;
}
public Minimum combine(Minimum other) {
if (value > other.value) {
index = range + other.index;
value = other.value;
}
range += other.range;
return this;
}
public int getIndex() {
return index;
}
}
static Collector<Integer, Minimum, Integer> MIN_INDEX = new Collector<Integer, Minimum, Integer>() {
#Override
public Supplier<Minimum> supplier() {
return Minimum::new;
}
#Override
public BiConsumer<Minimum, Integer> accumulator() {
return Minimum::accept;
}
#Override
public BinaryOperator<Minimum> combiner() {
return Minimum::combine;
}
#Override
public Function<Minimum, Integer> finisher() {
return Minimum::getIndex;
}
#Override
public Set<Collector.Characteristics> characteristics() {
return Collections.emptySet();
}
};
Writing a collectors creates an annoying amount of code, but it can be easily generalized to support any comparable value. Also, calling the collector looks very idiomatic:
List<Integer> list = Arrays.asList(4,3,7,1,5,2,9);
int minIndex = list.stream().collect(MIN_INDEX);
If we change the accept and combine methods to always return a new Minimum instance (ie. if we make Minimum immutable), we can also use reduce:
int minIndex = list.stream().reduce(new Minimum(), Minimum::accept, Minimum::combine).getIndex();
I sense large potential for parallelization in this one.
I have this code below where I am inserting a new integer into a sorted LinkedList of ints but I do not think it is the "correct" way of doing things as I know there are singly linkedlist with pointer to the next value and doubly linkedlist with pointers to the next and previous value. I tried to use Nodes to implement the below case but Java is importing this import org.w3c.dom.Node (document object model) so got stuck.
Insertion Cases
Insert into Empty Array
If value to be inserted less than everything, insert in the beginning.
If value to be inserted greater than everything, insert in the last.
Could be in between if value less than/greater than certain values in LL.
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList<Integer> llist = new LinkedList<Integer>();
llist.add(10);
llist.add(30);
llist.add(50);
llist.add(60);
llist.add(90);
llist.add(1000);
System.out.println("Old LinkedList " + llist);
//WHat if you want to insert 70 in a sorted LinkedList
LinkedList<Integer> newllist = insertSortedLL(llist, 70);
System.out.println("New LinkedList " + newllist);
}
public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){
llist.add(value);
Collections.sort(llist);
return llist;
}
}
If we use listIterator the complexity for doing get will be O(1).
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(true) {
if (itr.hasNext() == false) {
itr.add(element);
return(true);
}
T elementInList = itr.next();
if (elementInList.compareTo(element) > 0) {
itr.previous();
itr.add(element);
System.out.println("Adding");
return(true);
}
}
}
}
This might serve your purpose perfectly:
Use this code:
import java.util.*;
public class MainLinkedList {
private static LinkedList<Integer> llist;
public static void main(String[] args) {
llist = new LinkedList<Integer>();
addValue(60);
addValue(30);
addValue(10);
addValue(-5);
addValue(1000);
addValue(50);
addValue(60);
addValue(90);
addValue(1000);
addValue(0);
addValue(100);
addValue(-1000);
System.out.println("Linked List is: " + llist);
}
private static void addValue(int val) {
if (llist.size() == 0) {
llist.add(val);
} else if (llist.get(0) > val) {
llist.add(0, val);
} else if (llist.get(llist.size() - 1) < val) {
llist.add(llist.size(), val);
} else {
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
}
}
}
This one method will manage insertion in the List in sorted manner without using Collections.sort(list)
You can do it in log (N) time Complexity simply. No need to iterate through all the values. you can use binary search to add value to sorted linked list.just add the value at the position of upper bound of that function.
Check code... you may understand better.
public static int ubound(LinkedList<Integer> ln, int x) {
int l = 0;
int h = ln.size();
while (l < h) {
int mid = (l + h) / 2;
if (ln.get(mid) <= x) l = mid + 1;
else h = mid;
}
return l;
}
public void solve()
{
LinkedList<Integer> ln = new LinkedList<>();
ln.add(4);
ln.add(6);
ln.add(ubound(ln, 5), 5);
out.println(ln);
}
Output : [4, 5, 6]
you can learn about binary search more at : https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/
#Atrakeur
"sorting all the list each time you add a new element isn't efficient"
That's true, but if you need the list to always be in a sorted state, it is really the only option.
"The best way is to insert the element directly where it has to be (at his correct position). For this, you can loop all the positions to find where this number belong to"
This is exactly what the example code does.
"or use Collections.binarySearch to let this highly optimised search algorithm do this job for you"
Binary search is efficient, but only for random-access lists. So you could use an array list instead of a linked list, but then you have to deal with memory copies as the list grows. You're also going to consume more memory than you need if the capacity of the list is higher than the actual number of elements (which is pretty common).
So which data structure/approach to take is going to depend a lot on your storage and access requirements.
[edit]
Actually, there is one problem with the sample code: it results in multiple scans of the list when looping.
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
The call to get(i) is going to traverse the list once to get to the ith position. Then the call to add(i, val) traverses it again. So this will be very slow.
A better approach would be to use a ListIterator to traverse the list and perform insertion. This interface defines an add() method that can be used to insert the element at the current position.
Have a look at com.google.common.collect.TreeMultiset.
This is effectively a sorted set that allows multiple instances of the same value.
It is a nice compromise for what you are trying to do. Insertion is cheaper than ArrayList, but you still get search benefits of binary/tree searches.
Linked list isn't the better implementation for a SortedList
Also, sorting all the list each time you add a new element isn't efficient.
The best way is to insert the element directly where it has to be (at his correct position).
For this, you can loop all the positions to find where this number belong to, then insert it, or use Collections.binarySearch to let this highly optimised search algorithm do this job for you.
BinarySearch return the index of the object if the object is found in the list (you can check for duplicates here if needed) or (-(insertion point) - 1) if the object isn't allready in the list (and insertion point is the index where the object need to be placed to maintains order)
You have to find where to insert the data by knowing the order criteria.
The simple method is to brute force search the insert position (go through the list, binary search...).
Another method, if you know the nature of your data, is to estimate an insertion position to cut down the number of checks. For example if you insert 'Zorro' and the list is alphabetically ordered you should start from the back of the list... or estimate where your letter may be (probably towards the end).
This can also work for numbers if you know where they come from and how they are distributed.
This is called interpolation search: http://en.wikipedia.org/wiki/Interpolation_search
Also think about batch insert:
If you insert a lot of data quickly you may consider doing many insertions in one go and only sort once afterwards.
Solution of Amruth, simplified:
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(itr.hasNext()) {
if (itr.next().compareTo(element) > 0) {
itr.previous();
break;
}
}
itr.add(element);
}
}
Obviously it's O(n)
I am creating a partially ordered set as an abstract data type in java, and I have to make an iterator version of the set of numbers, and an iterator for the relations. Now for the elements, I've used HashSet of integer, and for the relations, I've used an ArrayList of pairs (pairs is a class I created that takes 2 ints as parameter which basically is like (x, y)). I need to make 2 iterators, one for s and one for r, but they have to follow a certain ordering,
1. if (x, y) belong to R, then the iterator of s should return x before it returns y
2. if (x, y) and (y, z) belong to R, then iterator of r should return (x, y) before it returns (y, z)
I made a helper method that check first for to check if the element n in the set is the first element in a pair then it returns it, but I cant seem to check if it is second element, how can I check for the first element if it is returned or not?
Here is my code:
private class IntGenerator implements Iterator {
private Iterator<Integer> i;
public IntGenerator () {
i = S.iterator();
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInFirstElmPair(p, n)) return n;
else (isInSecondElmPair(p, n)) {
// should check for the first element
// if it was returned or not
}
}
}
public void remove() { throw new UnsupportedOperationException(); }
}
I would really appreciate any kind of help, or hint in this code.
Thanks
EDIT:
Okay, I've wrote the code to it after adding a new set which will hold the returned elements, and this is what I wrote:
Set<Integer> returnedNumbers = new HashSet<Integer> ();
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInSecondElmPair(p, n)) {
if (returnedNumbers.contains(p.getFirstElm())) {
returnedNumbers.add(n);
return n;
}else{
returnedNumbers.add(p.getFirstElm());
return p.getFirstElm();
}
}else{
returnedNumbers.add(n);
return n;
}
}
}
Is this code correct? Also, eclipse seems to give me an error telling me I need to return a value outside the loop, but I already returned inside for every case why does it need more?
Appreciate the help
Well, to check if a value was previously returned, you of course need to keep track of all values that were returned previously.
So in your iterator, you could define
Set<Integer> previouslyReturned = new HashSet<Integer>();
and then, before returning it in your for loop, add it there:
if (isInFirstElmPair(p, n)) {
previouslyReturned.add(n);
return n;
}
else (isInSecondElmPair(p, n)) {
if (previouslyReturned.contains(n) {
// do one thing
} else {
// do another thing
}
}
This way, however, you are constructing a set of s in the order in which it shall be returned inside the iterator. It would make sense to create this once (consider a LinkedHashSet), keep it somewhere else and iterate over it.
Generally I am not sure that this approach will lead to what you want. Do you know anything about theorder of elements in S and R? If the iteration order is arbitrary (i.e. because relations were added in unpredictable order) then the iterator will first return the first half of the first relation pair, even if that element is in the second half of another pair. Do you have to use an element HashSet and a relation List?