What is the purpose of t1.next=null below the while loop? - java

public class Solution {
public static LinkedListNode<Integer> removeDuplicates(LinkedListNode<Integer> head) {
//Your code goes here
if(head==null){
return head;
}
if(head.next==null){
return head;
}
LinkedListNode<Integer> t1=head, t2=head.next;
LinkedListNode<Integer> final_head=head;
while(t2!=null){
if(t1.data==t2.data){
t2=t2.next;
}else{
t1.next=t2;
t1=t2;
}
}
t1.next=null;
return final_head;
}
}
Why is it showing runtime error when I remove t1.next=null ?
Am I missing something here ? I dont undertand the purpose of t1.next=null.

Answering why t1.next = null is needed from a correctness point of view...
Consider a linked list like this
1 -> 2 -> 3 -> 3 -> NULL
....Skipping a few initial iterations of the loop.... and when t1 is and t2 are pointing to the penultimate 3.
1 -> 2 -> 3 -> 3 -> NULL
↑
t1
t2
The if condition would be true and you would move t2 to the last 3 (while t1 still points to the penultimate 3).
1 -> 2 -> 3 -> 3 -> NULL
↑ ↑
t1 t2
On the next iteration, the same if condition would be true and you would make t2 null and break out of the while loop.
1 -> 2 -> 3 -> 3 -> NULL
↑ ↑
t1 t2
Now, to get the effect of removing the duplicate 3s, you should make the next of t1 as null.
From this,
1 -> 2 -> 3 -> 3 -> NULL
↑
t1
Setting t1.next = null results in,
1 -> 2 -> 3 -> NULL
↑
t1

Related

Are multiple comparators being returned?

PriorityQueue<Student> pq = new PriorityQueue<(
Comparator.comparing(Student::getCgpa).reversed()
.thenComparing(Student::getFname)
.thenComparing(Student::getToken)
);
Are multiple comparators being returned? If so, how,
because this constructor only returns one.
"Are multiple comparators being returned?" - Yes, on a techical level. Each Comparator except for the last in the chain is used to create another Comparator (through the calls reversed() and thenComparing()). But only one is passed along as a parameter to the PriorityQueue:
Comparator.comparing(Student::getCgpa) // <- 1st comparator created & returned
.reversed() // <- 2nd comparator created & returned
.thenComparing(Student::getFname) // <- 3nd comparator created & returned
.thenComparing(Student::getToken) // <- 4th comparator created, returned & passed along as argument
Are multiple comparators being returned?
No
if so how because this constructoronly returns one?
From the thenComparing documentation, the given comparator is chained with the previous in one Comparator that can use several rules to sort values
From the code
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
The new comparator apply this
use its own comparing test
if value is 0 (equals element) then the parameter one is used to return its decision
So in fact, using multiple chaining results in recursivse tests
Comparator<Foo> cmp = Comparator.comparingInt(Foo::getA)
.thenComparing(Foo::getB)
.thenComparing(Foo::getC)
.thenComparing(Foo::getD);
getA -> 1
-> -1
-> 0 -> getB -> 1
-> -1
-> 0 -> getC -> 1
-> -1
-> 0 -> getC -> 1
-> -1
...

Fibonacci using Stream And BinaryOperator in Java

I'm student and I learning functional Java 8. I got project to do and I don't understand how this function interface work. My teacher told me "you should know that" and I'm looking for help to understand this problem. It should count Fibonacci series
I got this code
StreamUtils.generateRest(Stream.of(1, 1), (a, b) -> a + b)
.limit(7)
.forEach(System.out::println);
StreamUtils.generateRest(Stream.of("AAA", "BB", "KKKK"), (a, b) -> a + b)
.limit(7)
.forEach(System.out::println);
StreamUtils.generateRest(Stream.of(i -> 0),
(BinaryOperator<UnaryOperator<Integer>>) (f, g) -> (x -> x == 0 ? 1 : x * g.apply(x - 1)))
.limit(10)
.map(f -> f.apply(7))
.forEach(System.out::println);
I did something like this but it doesn't work
public class StreamUtils<T> {
public static <T> Stream generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
return Stream.of(stream.reduce((a, b) -> binaryOperator.apply(a, b)));
}
}
Someone can help me with that and explain how to solve this problem?
To make first example work you need to implement something like this:
private static class StreamUtils<T> {
public static <T> Stream generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
return Stream.iterate(stream.toArray(), p -> new Object[]{p[1], binaryOperator.apply((T) p[0], (T) p[1])})
.flatMap(p -> Stream.of(p[0]));
}
}
It creates array from your input stream, then applies passed function on two elements, shifts the result of previous iteration to position 0, as we need previous two values to calculate next.
And then it creates unlimited stream of calculated Fibonacci elements.
The output is:
1
1
2
3
5
8
13
And version with correct generics usage, because you initial structure produces raw types.
private static class StreamUtils {
public static <T> Stream<T> generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
return Stream.iterate(stream.toArray(), p -> new Object[]{p[1], binaryOperator.apply((T) p[0], (T) p[1])})
.flatMap(p -> Stream.of((T) p[0]));
}
}
I'm assuming that having more than 2 items means A, B, C, A+B, B+C, C+(A+B), (A+B)+(B+C), etc., and that having 1 item means A, A+A, A+(A+A), (A+A)+(A+(A+A)), etc., where + is the binary operator.
Basically you turn the stream into an array, then you use Stream.generate and at each step you generate the element after the ones you have, shift the array left to fit the new element, and return the old first element (which is no longer in the array). Note that since this has side effects (modifying an external array) it cannot be used with .parallel().
#SuppressWarnings("unchecked")
public static <T> Stream<T> generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
T[] t = (T[]) stream.toArray();
if (t.length == 1) {
t = (T[]) new Object[] { t[0], binaryOperator.apply(t[0], t[0]) };
}
final T[] items = t;
return Stream.generate(() -> {
T first = items[0];
T next = binaryOperator.apply(items[0], items[1]);
System.arraycopy(items, 1, items, 0, items.length - 1);
items[items.length - 1] = next;
return first;
});
}
Output:
1
1
2
3
5
8
13
AAA
BB
KKKK
AAABB
BBKKKK
KKKKAAABB
AAABBBBKKKK
0
0
0
0
0
0
0
0
5040
5040

Stream Hash Map using Lambda

Example SQL Result
dataResult
Code Amt TotalAmtPerCode
A1 4 0
A1 4 0
B1 4 0
B1 5 0
A1 6 0
with this result
i would like to ask on how to compute the TotalAmtPerCode
The expected result should be
Code Amt TotalAmtPerCode
A1 4 14
A1 4 14
B1 4 9
B1 5 9
A1 6 14
sample code
for (Map<String, Object> data: dataResult) {
Long total = ComputeTotalAmount(dataResult,data.get(DBColumn.Code.name();
container.setTotalAmtPerCode(total);
}
function that computes the total amount
private static long ComputeTotalAmount(List<Map<String, Object>> list, String code) {
Long total = 0;
for (Map<String, Object> data: dataResult) {
if (code.equals(data.get(DBColumn.Code.name()))) {
total = total+Long.valueOf(data.get(DBColumn.Code.name()).toString)
}
}
}
This one is working fine but I would like to ask for an optimization on this code. Because if I would loop 10,000 records, it would check 1st record for the Code then reiterate the 10k to find the same Code and get the amount on that code and sum it all then it would check the 2nd record and so-on.
Welcome to StackOverflow :)
As far as I see you need to group the sum of TotalAmtPerCode values by the Code. There exist a method Stream::collect to transform the values to the desired output using Collectors::groupingBy collector which groups the Stream<T> into Map<K, V> where V is a collection.
Map<String, Integer> map = dataresult.stream()
.collect(Collectors.groupingBy( // Group to Map
d -> d.get(DBColumn.Code.name()), // Key is the code
Collectors.summingInt(d -> d.get(DBColumn.TotalAmtPerCode.name())))); // Value is the sum
Note:
You might need to edit d -> d.get(DBColumn.Code.name()) and d.get(DBColumn.TotalAmtPerCode.name()) according to your needs to get the Code and TotalAmtPerCode - I dont know the data model.
I assume the TotalAmtPerCode is int. Otherwise, use Collectors.summingLong.
You could use Collectors.groupingBy():
Map<String, Long> collect = list.stream()
.collect(Collectors.groupingBy(
p -> p.getFirst(),
Collectors.summingLong(p -> p.getSecond())
)
);
This groups the input by some classifier (here it's p -> p.getFirst(), this will be probably something like data.get(DBColumn.Code.name()) in your case) and summarizes the values (p -> p.getSecond(), which must be changed to something like Long.valueOf(data.get(DBColumn.Code.name()).toString)).
Note: getFirst() and getSecond() are methods from org.springframework.data.util.Pair.
Example:
List<Pair<String, Long>> list = new ArrayList<>();
list.add(Pair.of("A1", 1L));
list.add(Pair.of("A1", 2L));
list.add(Pair.of("B1", 1L));
Map<String, Long> collect = list.stream()
.collect(Collectors.groupingBy(
p -> p.getFirst(),
Collectors.summingLong(p -> p.getSecond())
)
);
System.out.println(collect);
Output:
{A1=3, B1=1}

lambdas in removeIf

HashSet<Integer> liczby = new HashSet<Integer>();
liczby.add(1);
liczby.add(2);
liczby.add(3);
liczby.add(4);
liczby.removeIf ((Integer any) -> { return liczby.contains(3); });
for(Iterator<Integer> it = liczby.iterator(); it.hasNext();){
Integer l2 = it.next();
System.out.println(l2);
}
I can't understand why removeIf deletes not only 3 but also 1 and 2 condition should be satisfied only by 3...
Think of it this way... as long as the set contains 3 it will keep removing hence the current outcome.
If you want to remove the 3 only then do this:
liczby.removeIf(e -> e == 3);
The lambda is applied on each element and check if 3 is present, if yes it will delete the element :
1 -> 3 is present -> delete 1
2 -> 3 is present -> delete 2
3 -> 3 is present -> delete 3
4 -> 3 is not present -> don't delete 4
To remove all 3 element, you can use one of those solutions :
liczby.removeIf(any -> any.equals(3));
//-------------------------------------------------
liczby.removeIf(new Integer(3)::equals);
//-------------------------------------------------
Integer toRemove = 3;
liczby.removeIf(toRemove::equals);
TIPS
Your lambda can be simplified as :
liczby.removeIf(any -> liczby.contains(3));
For-each loop might be easier to use for simple iteration :
for(Integer i : liczby){
System.out.println(i);
}

Using takeWhileWithIndex to iterate over array of index and then emit an observable

I have a list of number that every number represents an index.
I would like to go through the list one by one and for every number emit an observable.
How can I do that?
I have this snippet, but I having troubles understanding how to continue...
List<Short> seats = Arrays.asList(new Short[]{0,2,3,1});
rx.Observable.from(seats).takeWhileWithIndex((seatIdx, idx) -> {
// Here I would like to emit an Observable
updateGame(seatIdx, idx == 0 ? true : false)
.subscribe(results -> {
System.out.println(results);
});
return !seats.isEmpty();
}).subscribe();
There must be a better way to do this...
If you have any idea...
Thanks!
EDIT
I would like to go one step further and after omitting the loop of 4 iterations (which I don't care about its results), I would like to continue with the chain and concatenate more Observables.
List<Short> seats = Arrays.asList(new Short[]{0,2,3,1});
rx.Observable.range(0, seats.size())
.zipWith(seats, (idx, seatIdx) -> {
return updateGame(seatIdx, idx == 0 ? true : false);
})
.takeLast(1)
.flatMap(x -> x)
.concatWith(calculatePayout(...))
.concatWith(persistGame(...))
.subscribe(results -> {
System.out.println(results);
}, e -> {
}, () -> {
System.out.println("COMPLETED");
});
Notice, I use 'takeLast(1)' in order to avoid calling 'calculatePay' 4 times! - is there more elegant way to do this?
zip with Iterable gives you what you need:
List<Short> seats = Arrays.asList(new Short[]{0,2,3,1});
Observable.range(0, seats.size())
.zipWith(seats,
(idx, seatIdx) ->
updateGame(seatIdx, idx == 0 ? true : false))
.flatMap(x -> x)
.doOnNext(System.out::println)
.subscribe();

Categories